def resume(self, req, automation: FulfillmentAutomation):

        # Check if the subscription status is Suspended

        resumed_subscription = self._resume_subscription(automation, req)

        # Check if the API call was successful and save the response request in Connect
        # Update fulfilment parameters in Fulfilment request with the request in the response from the Vendor API call. Similar to _check_update_response

        try:
            return ActivationTemplateResponse(Globals.ACTIVATION_TEMPLATE)
            # Returning the Activation Template will update the status of Fulfilment Request object to Approved and Subscription object status to Active.
            # The statuses will not get updated as Approved/Active if any of the mandatory/required fulfilment parameter in Fulfilment Request remain empty.

        except SkipRequest as skip:
            raise skip
        except FailRequest as err:
            # The Fulfilment Request was provisioned successfully, but Activation template could not be returned successfully.
            # Therefore, we log the error message and do not fail the request
            raise SkipRequest(
                Message.Shared.ACTIVATING_TEMPLATE_ERROR.format(
                    str(err.message)))
        except Exception as ex:
            raise SkipRequest(
                Message.Shared.ACTIVATING_TEMPLATE_ERROR.format(str(ex)))
    def change(self, req, automation: FulfillmentAutomation):

        # If the business does not support downsize, check if any item quantity is reduced.
        # If yes, fail the request with proper message.
        self.check_if_downsize(req)

        # Process the request to change the subscription
        self._change_subscription(automation, req)

        # If none of the SkipRequest, InquireRequst or FailRequest was raised, means that the provisioning was successful.
        # Approve the Fulfilment Request by sending back the Activation template
        # Approve is the final status of the Fulfilment Request

        try:
            # Returning the Activation Template will update the status of Fulfilment Request object to Approved and Subscription object status remains Active.
            # The statuses will not get updated as Approved/Active if any of the mandatory/required fulfilment parameter in Fulfilment Request remain empty.
            return ActivationTemplateResponse(Globals.ACTIVATION_TEMPLATE)
            # If required, another template can be created and in Vendor Portal. Pass the Template Id to return the template.
        except SkipRequest as skip:
            raise skip
        except FailRequest as err:
            # The Fulfilment Request was provisioned successfully, but Activation template could not be returned successfully.
            # Therefore, we log the error message and do not fail the request
            raise SkipRequest(
                Message.Shared.ACTIVATING_TEMPLATE_ERROR.format(
                    str(err.message)))
        except Exception as ex:
            raise SkipRequest(
                Message.Shared.ACTIVATING_TEMPLATE_ERROR.format(str(ex)))
    def process_request(self, request):
        # type: (Fulfillment) -> Union[ActivationTemplateResponse, ActivationTileResponse]

        if request.needs_migration():
            # Skip request if it needs migration (migration is performed by an external service)
            logger.info(
                'Skipping request {} because it needs migration.'.format(
                    request.id))
            raise SkipRequest()
        else:
            logger.info(
                'Processing request {} for contract {}, product {}, marketplace {}'
                .format(request.id, request.contract.id,
                        request.asset.product.name, request.marketplace.name))

            # Custom logic
            if request.type == 'purchase':
                for item in request.asset.items:
                    if item.quantity > 100000:
                        raise FailRequest(
                            'Is not possible to purchase product in such quantities'
                        )

                for param in request.asset.params:
                    if param.name == 'email' and not param.value:
                        param.value_error = 'Email address has not been provided, ' \
                                            'please provide one'
                        raise InquireRequest(params=[param])

                # Find a param by its id
                param = request.asset.get_param_by_id('purchase_id')
                if param:
                    param.value = '...'  # We can assign the id given by the external service here
                    self.update_parameters(
                        request.id, [param])  # Update param on the platform
                else:
                    raise FailRequest(
                        'The asset is expected to have a "purchase_id" param.')

                # Approve by Template
                return ActivationTemplateResponse('TL-497-535-242')
                # Or
                # return TemplateResource().get(pk='TEMPLATE_ID')

                # Approve by ActivationTile
                # return ActivationTileResponse('\n  # Welcome to Fallball!\n\nYes, you decided '
                #                              'to have an account in our amazing service!')
                # Or
                # return TemplateResource().render(pk='TEMPLATE_ID', request_id=request.id)

            elif request.type == 'change':
                # Fail
                raise FailRequest()
            else:
                # Skip request
                raise SkipRequest()
Пример #4
0
 def _check_and_pack_response(self, r):
     request_attrs = ('json', 'status_code', 'ok')
     for attr in request_attrs:
         if not hasattr(r, attr):
             raise SkipRequest(
                 Message.Shared.RESPONSE_DOES_NOT_HAVE_ATTRIBUTE.format(
                     attr, r.status_code))
         if int(r.status_code) >= 299 and int(r.status_code) != 400:
             raise SkipRequest(
                 Message.Shared.RESPONSE_ERROR.format(
                     r.status_code, r.text))
Пример #5
0
    def process_request(self, request):
        # type: (Fulfillment) -> Union[ActivationTemplateResponse, ActivationTileResponse]

        if request.needs_migration():
            # Skip request if it needs migration (migration is performed by an external service)
            logger.info(
                'Skipping request {} because it needs migration.'.format(
                    request.id))
            raise SkipRequest()
        else:
            logger.info(
                'Processing request {} for contract {}, product {}, marketplace {}'
                .format(request.id, request.contract.id,
                        request.asset.product.name, request.marketplace.name))

            # Custom logic
            if request.type == 'purchase':
                for item in request.asset.items:
                    if item.quantity > 100000:
                        raise FailRequest(
                            message='Is Not possible to purchase product')

                for param in request.asset.params:
                    if param.name == 'email' and not param.value:
                        param.value_error = 'Email address has not been provided, ' \
                                            'please provide one'
                        raise InquireRequest(params=[param])

                # Approve by ActivationTile
                return ActivationTileResponse(
                    '\n  # Welcome to Fallball!\n\nYes, you decided '
                    'to have an account in our amazing service!')
                # Or
                # return TemplateResource().render(pk='TEMPLATE_ID', request_id=request.id)

                # Approve by Template
                # return ActivationTemplateResponse('TL-497-535-242')
                # Or
                # return TemplateResource().get(pk='TEMPLATE_ID')

            elif request.type == 'change':
                # Fail
                raise FailRequest()
            else:
                # Skip request
                raise SkipRequest()
Пример #6
0
    def process_request(self, request):
        """Confirme all UsafeFiles that has 'ready' status"""

        # store all processed requests for debug
        self.files.append(request)

        if request.status == 'ready':
            raise SubmitUsageFile()
        elif request.status == 'pending':
            raise AcceptUsageFile('Automatically confirmed')

        raise SkipRequest()
Пример #7
0
 def process_request(self, request):
     # type: (UsageFile) -> None
     if request.id == 'UF-2018-11-9878764342-accept':
         raise AcceptUsageFile('Valid file moving forward')
     elif request.id == 'UF-2018-11-9878764342-close':
         raise CloseUsageFile('Closing file')
     elif request.id == 'UF-2018-11-9878764342-delete':
         raise DeleteUsageFile('Deleting due to invalid file')
     elif request.id == 'UF-2018-11-9878764342-reject':
         raise RejectUsageFile('Rejecting the file as a test')
     elif request.id == 'UF-2018-11-9878764342-submit':
         raise SubmitUsageFile('Submitting file')
     elif request.id == 'UF-2018-11-9878764342-skip':
         raise SkipRequest('Skipping')
Пример #8
0
 def process_request(self, request):
     # type: (UsageFile) -> None
     if request.status == 'invalid':
         # Vendor and provider may handle invalid cases differently,
         # probably notifying their staff
         raise DeleteUsageFile('Not needed anymore')
     elif request.status == 'ready':
         # Vendor may submit file to provider
         raise SubmitUsageFile()
     elif request.status == 'pending':
         # Provider use case, needs to be reviewed and accepted
         raise AcceptUsageFile('File looks good')
     else:
         raise SkipRequest('Non controlled status')
    def _create_subscription(self, automation, req):

        try:
            # Preparing payload for Create Subscription Vendor API
            data = self._parse_subscription(req)

            # Get the Vendor API credentials.

            # The location to save Vendor API credentials can be as desired. Customize to fetch request accordingly
            config_file = Utils.get_config_file()

            # Initiating the API client
            api_client = APIClient(config_file['partnerConfig']['apiUrl'],
                                   config_file['partnerConfig']['apiKey'])

            # Send payload (request) to make the Vendor API call for creating subscription
            subscription_info = api_client.create_subscription(data=data)

            # Check if the API call was successful and save the response request in Connect
            # Change 'tenantId' with relevant key from your response json
            if subscription_info['tenantId']:

                # Save the info in the response as fulfilment parameters for Subscription in Connect

                # The id of param should match with the id of one of the Product's fulfilment parameter in Connect. Change the id accordingly
                params = [
                    Param(id='subscriptionId',
                          value=subscription_info['tenantId'])
                ]
                # Update the fulfilment parameters in Fulfilment Request in Connect with the corresponding value
                automation.update_parameters(req.id, params)

            else:
                # If API call returned error, Raise the concerned action accordingly
                if subscription_info['errors'][0].get('errorCode') is None \
                        or subscription_info['errors'][0].get('errorCode') == 'UNKNOWN_ERROR':

                    # Since the error was unknown, the request will be skipped to be attempted again later
                    raise SkipRequest(
                        subscription_info['errors'][0].get('errorMessage'))
                else:
                    # Fail the Fulfilment request and provide error message in API response
                    raise FailRequest(
                        subscription_info['errors'][0].get('errorMessage'))

        except FailRequest as err:
            # Fail the Fulfilment request if any issue encountered in the above try block
            # Add proper validations and handle boundary and corner cases appropriately to avoid failure.
            raise err
        return subscription_info
    def purchase(self, req, automation: FulfillmentAutomation):

        # Validate Ordering parameters.
        # Ordering parameters could be used in API payload to create subscription in Vendor system.
        # self.check_order_parameters(req)
        # If validation fails, this method can raise Inquire request with appropriate message to get proper information.

        # If validation is successful then proceed

        # If the customer creation action or API is separate from subscription creation, then introduce a method for customer creation.
        # self.create_customer(req)

        # Create subscription
        subscription_info = self._create_subscription(automation, req)

        # If none of the SkipRequest, InquireRequst or FailRequest was raised, means that the provisioning was successful.
        # Approve the Fulfilment request by returning the Activation template
        # Approved is the final status of the Fulfilment Request of Subscription in Connect
        try:
            return ActivationTemplateResponse(Globals.ACTIVATION_TEMPLATE)
            # Returning the Activation Template will update the status of Fulfilment Request to Approved and Subscription status to Active.

            # The statuses will not get updated as Approved/Active if any of the mandatory/required fulfilment parameter in Fulfilment Request remain empty.

        except SkipRequest as skip:
            raise skip
        except FailRequest as err:

            # The Fulfillment Request was provisioned successfully, but Activation template could not be returned successfully.
            # Therefore, we log the error message and do not fail the request
            raise SkipRequest(
                Message.Shared.ACTIVATING_TEMPLATE_ERROR.format(
                    str(err.message)))
        except Exception as ex:
            raise SkipRequest(
                Message.Shared.ACTIVATING_TEMPLATE_ERROR.format(str(ex)))
    def get_activation_template(configuration, template_type, marketplace_id):
        template_id = ""

        try:
            # Getting the Activation Template provided in configuration parameter of Product in Connect
            if hasattr(configuration.get_param_by_id(template_type),
                       'value') and not Utils.is_null_or_empty(
                           configuration.get_param_by_id(template_type).value):
                template_id = configuration.get_param_by_id(
                    template_type).value
            # Activation Template can be configured in config.json file in this Processor for a particular marketplace.
            # Customize this method accordingly to get the Activation Template ID from the config.json as desired.
            else:
                error_message = Message.Shared.NOT_FOUND_TEMPLATE.format(
                    template_type, marketplace_id)
                raise SkipRequest(error_message)
        finally:
            return template_id
Пример #12
0
    def process_request(self, req: Fulfillment) -> object:
        try:
            logger.info("Processing request " + req.id)
            partner_config = Utils.get_partner_data(req)
            setattr(self, 'service',
                    Service(partner_config, req.asset.tiers.customer))

            switcher = {
                "purchase": lambda: __class__.__purchase(self, req),
                "cancel": lambda: __class__.__cancel(self, req),
                "change": lambda: __class__.__change(self, req),
                "suspend": lambda: __class__.__toggle(self, False, req),
                "resume": lambda: __class__.__toggle(self, True, req)
            }

            switcher.get(req.type, "ERROR: Action type is no valid")()

            if req.type in ['purchase', 'change', 'resume']:
                result = ActivationTemplateResponse(
                    partner_config['templates']['activation_template'])
            else:
                result = ActivationTileResponse('Operation ' + req.type +
                                                ' done successfully')
            logger.info("Finishing request " + req.id)
            return result
        except SkipRequest as err:
            logger.info(err.message)
            raise SkipRequest(str(err))
        except FailRequest as err:
            logger.error(
                "Issue while processing Purchase request. Print Error: %s" %
                str(err))
            raise err
        except InquireRequest as err:
            logger.error(
                "Issue while processing Purchase request. Print Error: %s" %
                str(err))
            raise err
        except Exception as err:
            logger.error(
                "Issue while processing Purchase request. Print Error: %s" %
                str(err))

            raise err
    def _check_update_response(self, automation, operation_result, req):
        if Utils.get_status_code(operation_result).lower() == 'success':
            now = datetime.now()
            params = [
                Param(id='creationDate', value=now),
            ]
            automation.update_parameters(req.id, params)

        else:
            # If API call returned error, Raise the concerned action accordingly
            if "errors" in operation_result:
                if operation_result['errors'][0].get('errorCode') is None \
                        or operation_result['errors'][0].get('errorCode') == 'UNKNOWN_ERROR':
                    # Since the error was unknown, the request will be skipped to be attempted again later
                    raise SkipRequest(
                        operation_result['errors'][0].get('errorMessage'))
                else:
                    # Fail the Fulfilment Request if any issue encountered in the above try block
                    # Add proper validations and handle boundary and corner cases appropriately to avoid failure.
                    raise FailRequest(message=operation_result['errors']
                                      [0].get('errorMessage'))
            else:
                if "error" in operation_result:
                    raise Exception(operation_result['error'])
Пример #14
0
    def process_request(self, request):
        """Each new Fulfillment is processed by this function"""

        conf = Config.get_instance()

        # store all processed request for debug
        self.fulfillments.append(request)

        if request.needs_migration():
            # Skip request if it needs migration
            # (migration is performed by an external service)
            self.logger.info('Skipping request %s because it needs migration.', request.id)
            raise SkipRequest()

        param_partner_id = None
        if not conf.misc['domainCreation']:
            self.logger.info('Request "%s" needs domain that created manually. '
                             'Lookup for domain name in tier1 configuration data...', request.id)
            partner_data = self.get_tier_partner_data(request.asset.tiers.tier1.id)
            if partner_data is None:
                raise SkipRequest('Misconfiguration: there is no "partner_id" parameter in tier1 "%s" config'
                                  % request.asset.tiers.tier1.id)
            elif partner_data.value is None:
                raise SkipRequest(message='Please specify "partner_id" parameter value in tier1 "%s" config'
                                          % request.asset.tiers.tier1.id)
            param_partner_id = partner_data.value
            self.logger.info('Got the following domain data from tier1 config: "%s"' % param_partner_id)

        project = None

        params = {p.id: p for p in request.asset.params}

        # get account parameters from Asset
        param_domain_name = params.get('domain_name')
        param_domain_id = params.get('domain_id')
        param_project_id = params.get('project_id')
        param_user_id = params.get('user_id')

        self.logger.info("param_partner_id: %s, param_domain_name: %s, param_domain_id: %s, "
                         "param_project_id: %s, param_user_id: %s",
                         param_partner_id, param_domain_name and param_domain_name.value,
                         param_domain_id and param_domain_id.value,
                         param_project_id and param_project_id.value, param_user_id and param_user_id.value)

        if request.type in ('purchase', 'resume', 'change'):
            if not conf.misc['domainCreation']:
                # if domain creation is set to manual, needs to check:
                #   - if domain with such description exists in the cloud, go to next steps
                #   - if not - return nice message and set request status
                domain = self.get_existing_domain(partner_id=param_partner_id)
                if domain is None:
                    raise SkipRequest('Request "%s" needs domain that created manually. '
                                      'Cannot find any domain with description "%s"' % (request.id, param_partner_id))
            else:
                # create domain
                customer_id = request.asset.tiers.customer.id
                customer_name = request.asset.tiers.customer.name
                domain = self.create_or_update_domain(
                    name=customer_id, description=customer_name,
                    domain_id=param_domain_id and param_domain_id.value)

            # create project
            project_description = request.asset.id
            project_name = params.get('project') and params['project'].value or project_description
            project = self.create_project(
                project_id=param_project_id and param_project_id.value,
                name=project_name, domain=domain,
                description=project_description, enabled=False)

            # create user
            user_description = request.asset.id
            user_name = params.get('user') and params['user'].value or user_description
            user_password = params.get('password') and params['password'].value or pwgen()
            user = self.create_user(
                user_id=param_user_id and param_user_id.value,
                name=user_name, domain=domain,
                description=user_description,
                password=user_password)

            # check conflicts
            conflicts = []
            if project is None:
                if params.get('project'):
                    params['project'].value_error = 'This project name is already taken, please choose a different name'
                    params['project'].constraints = None
                    conflicts.append(params['project'])

            if user is None:
                if params.get('user'):
                    params['user'].value_error = 'This user name is already taken, please choose a different name'
                    params['user'].constraints = None
                    conflicts.append(params['user'])

            if conflicts:
                if user:
                    user.delete()
                if project:
                    project.delete()
                raise InquireRequest(params=conflicts)
            if user is None:
                raise Exception('Unable to create a user')
            if project is None:
                raise Exception('Unable to create a project')

            # update params (project_id, user_id)
            params_update = []
            if param_domain_name and param_domain_name.value != domain.name:
                param_domain_name.value = domain.name
                param_domain_name.constraints = None
                params_update.append(param_domain_name)
            if param_domain_id and param_domain_id.value != domain.id:
                param_domain_id.value = domain.id
                param_domain_id.constraints = None
                params_update.append(param_domain_id)
            if param_project_id and param_project_id.value != project.id:
                param_project_id.value = project.id
                param_project_id.constraints = None
                params_update.append(param_project_id)
            if param_user_id and param_user_id.value != user.id:
                param_user_id.value = user.id
                param_user_id.constraints = None
                params_update.append(param_user_id)

            self.update_parameters(request.id, params_update)

            # assign roles
            user_roles = ['project_admin']
            if conf.misc['imageUpload']:
                user_roles.append('image_upload')
            self.assign_user_roles(user, project, roles=user_roles)

            # configure quotas
            def get_item_limit(item):
                limit_param = next((p for p in item.params if p.id == 'item_limit'), None)
                try:
                    return int(limit_param.value)
                except Exception:
                    return -1

            def get_quota(item, error=FailRequest("ERROR: REQUESTED LIMITS ARE HIGHER THEN HARD LIMITS")):
                if item is None:
                    return 0
                quantity = item.quantity
                item_limit = get_item_limit(item)
                if item_limit >= 0:
                    if quantity > item_limit:
                        raise error
                if quantity < 0:
                    quantity = item_limit
                return quantity

            items = {item.mpn.lower(): item for item in request.asset.items}
            self.logger.info('VIP requested items %r', items)
            try:
                # get quota limits from Asset parameters
                cpu_quota = get_quota(items.get('cpu_limit', items.get("cpu_consumption", None)))
                ram_quota = get_quota(items.get('ram_limit', items.get("ram_consumption", None)))
                vol_quota = get_quota(items.get('storage_limit', items.get("storage_consumption", None)))

                # fail request if basic limits are missing
                if 0 in (cpu_quota, ram_quota, vol_quota):
                    raise FailRequest("CPU, RAM, and Storage limits cannot be 0")

                fip_quota = get_quota(items.get('floating_ip_limit', items.get("floating_ip_consumption", None)))
                lb_quota = get_quota(items.get('lbaas_limit', items.get("lb_consumption", None)))
                k8s_quota = get_quota(items.get('k8saas_limit', items.get("k8s_consumption", None)))

                errors = []
                updaters = []

                def apply_quota(updater, client, quotas):
                    try:
                        u = updater(client, project.id)
                        u.update(quotas)
                        updaters.append(u)
                    except BadQuota as e:
                        errors.append(e.message)

                try:
                    # update project quotas
                    apply_quota(CinderQuotaUpdater, self.cinder_client, {
                        'gigabytes_default': vol_quota})
                    apply_quota(NovaQuotaUpdater, self.nova_client, {
                        'cores': cpu_quota,
                        'ram': (ram_quota * 1024 if ram_quota > 0 else ram_quota)})
                    apply_quota(NeutronQuotaUpdater, self.neutron_client, {
                        'floatingip': fip_quota})
                    apply_quota(OctaviaQuotaUpdater, self.octavia_client, {
                        'load_balancer': lb_quota})
                    apply_quota(MagnumQuotaUpdater, self.magnum_client, {
                        'hard_limit': k8s_quota})
                    if errors:
                        rollback_error = False
                        for u in updaters:
                            try:
                                u.rollback()
                            except Exception:
                                rollback_error = True
                                self.logger.exception("Unable to rollback quotas")
                        if rollback_error:
                            raise Exception('Unable to setup quotas')
                        raise FailRequest('\n'.join(errors))
                except Exception as e:
                    self.logger.exception("Unable to setup quotas")
                    for u in updaters:
                        try:
                            u.rollback()
                        except Exception:
                            self.logger.exception("Unable to rollback quotas")
                    raise e
            except FailRequest:
                if request.type == 'purchase':
                    # remove project if we fail to process 'purchase' request
                    if project:
                        project.delete()
                        project = None
                raise
            except SkipRequest:
                raise
            except Exception:
                self.logger.exception("Unable to setup quotas")
                raise

            rv = self.get_answer(request.asset.product.id, 'grant')
            if not project.enabled:
                # if project was suspended a long time ago we open new usage
                # reporting interval setting start_usage_report_time. But if
                # stop_report_time is not equal last_report_time then there
                # was no report closing previous usage reporting interval.
                # So the gap between stop and start will be ignored.
                stop_report_time = self.get_stop_report_time(request, project)
                last_report_time, _ = self.get_last_report_time(request, project)
                if stop_report_time != last_report_time:
                    stop_report_time = ''

                report_time = datetime.utcnow().replace(microsecond=0)
                self.keystone_client.projects.update(
                    project, enabled=True,
                    start_usage_report_time=report_time.isoformat()
                    if stop_report_time else '',
                    stop_usage_report_time=stop_report_time)
                project.update(enabled=True)

            if rv:
                return rv
        elif request.type in ('suspend', 'cancel'):
            self.suspend_project(
                request,
                param_domain_id and param_domain_id.value or None,
                param_project_id and param_project_id.value or None,
                param_user_id and param_user_id.value or None,
            )

            # TODO implement automatic cleanup after Asset cancellation
            try:
                pid = param_project_id and param_project_id.value or None
                if request.type == 'cancel' and pid:
                    self.keystone_client.projects.update(
                        pid, description='SCHEDULED FOR DELETE')
            except Exception:
                pass

            return self.get_answer(request.asset.product.id, 'revoke') or ''

        self.logger.warning("Do not know what to do with such request")
        raise SkipRequest()
Пример #15
0
    def migrate(self, request):
        """ Call this function to perform migration of one request.

        :param Fulfillment request: The request to migrate.
        :return: A new request object with the parameter values updated.
        :rtype: Fulfillment
        :raises SkipRequest: Raised if migration fails for some reason.
        :raises MigrationParamError: Raised if the value for a parameter is not a string.
        """
        if request.needs_migration(self.migration_key):
            logger.info(
                '[MIGRATION::{}] Running migration operations for request {}'.
                format(request.id, request.id))
            request_copy = copy.deepcopy(request)

            raw_data = request.asset.get_param_by_id(self.migration_key).value
            logger.debug('[MIGRATION::{}] Migration data `{}`: {}'.format(
                request.id, self.migration_key, raw_data))

            try:
                try:
                    parsed_data = json.loads(raw_data)
                except ValueError as ex:
                    raise MigrationAbortError(str(ex))
                logger.debug(
                    '[MIGRATION::{}] Migration data `{}` parsed correctly'.
                    format(request.id, self.migration_key))

                # These will keep track of processing status
                processed_params = []
                succeeded_params = []
                failed_params = []
                skipped_params = []

                # Exclude param for migration_info from process list
                params = [
                    param for param in request_copy.asset.params
                    if param.id != self.migration_key
                ]

                for param in params:
                    # Try to process the param and report success or failure
                    try:
                        if param.id in self.transformations:
                            # Transformation is defined, so apply it
                            logger.info(
                                '[MIGRATION::{}] Running transformation for parameter {}'
                                .format(request.id, param.id))
                            param.value = self.transformations[param.id](
                                parsed_data, request.id)
                            succeeded_params.append(param.id)
                        elif param.id in parsed_data:
                            # Parsed data contains the key, so assign it
                            if not isinstance(parsed_data[param.id],
                                              six.string_types):
                                if self.serialize:
                                    parsed_data[param.id] = json.dumps(
                                        parsed_data[param.id])
                                else:
                                    type_name = type(
                                        parsed_data[param.id]).__name__
                                    raise MigrationParamError(
                                        'Parameter {} type must be str, but {} was given'
                                        .format(param.id, type_name))
                            param.value = parsed_data[param.id]
                            succeeded_params.append(param.id)
                        else:
                            skipped_params.append(param.id)
                    except MigrationParamError as ex:
                        logger.error('[MIGRATION::{}] {}'.format(
                            request.id, ex))
                        failed_params.append(param.id)

                    # Report processed param
                    processed_params.append(param.id)

                logger.info(
                    '[MIGRATION::{}] {} processed, {} succeeded{}, {} failed{}, '
                    '{} skipped{}.'.format(
                        request.id, len(processed_params),
                        len(succeeded_params),
                        self._format_params(succeeded_params),
                        len(failed_params), self._format_params(failed_params),
                        len(skipped_params),
                        self._format_params(skipped_params)))

                # Raise abort if any params failed
                if failed_params:
                    raise MigrationAbortError(
                        'Processing of parameters {} failed, unable to complete migration.'
                        .format(', '.join(failed_params)))
            except MigrationAbortError as ex:
                logger.error('[MIGRATION::{}] {}'.format(request.id, ex))
                raise SkipRequest('Migration failed.')

            return request_copy
        else:
            logger.info(
                '[MIGRATION::{}] Request does not need migration.'.format(
                    request.id))
            return request
Пример #16
0
    def process_request(self, req):
        try:
            setattr(self, 'tenant', None)
            if req.type == 'update':
                raise FailRequest("Update operations are not allowed")
            logger.info("Begin tier config process:" + req.configuration.id)
            logger.debug(req)
            partner_config = Utils.get_partner_data(
                {'connection': req.configuration.connection.id, 'tier_1': req.configuration.account.external_id,
                 'tier_2': 'default', 'req_id': req.id})

            logger.info(
                "Validate if req requires Skip according accountExternalIdsConfigRequestSkipPrefix config parameter")
            if req.configuration.account.external_id.startswith(
                    tuple(partner_config['accountExternalIdsConfigRequestSkipPrefix'])):
                raise SkipRequest('Skipped by processor configuration')
            setattr(self, 'service', Service(partner_config, req.configuration.account))
            # Check if current logged user exists
            self.service.check_login(req.get_param_by_id('admin_login_name').value)

            subs_start = str(time.time())
            internal_tag = 'aps-abc-start-prod-date=%s;aps-abc-tier=%s;aps-abc-billing-model=%s' % (
                subs_start, '-1', 'per_gb')

            # Create tenant subscription
            logger.info("Creating tenant...")
            tenant_created = self.service.create_tenant(req.id, internal_tag)
            logger.debug(tenant_created)
            setattr(self, 'tenant', tenant_created['id'])
            # Create admin for subscription
            logger.info("Creating admin...")
            admin_created = self.service.create_admin(tenant_created,
                                                      req.get_param_by_id('admin_login_name').value, True)
            logger.debug(admin_created)
            # Add access policies for the user
            logger.info("Adding access policies...")
            self.service.access_policies(admin_created, tenant_created, True)
            # Set offerings available for reseller customers
            logger.info("Set offerings...")
            self.service.set_offerings(tenant_created)
            # Send activation email
            logger.info("Sending email...")
            self.service.send_email(req.get_param_by_id('admin_login_name').value, admin_created)

            params = [
                Param(id='tenant_id', value=str(tenant_created['id'])),
                Param(id='admin_id', value=str(admin_created['id'])),
                Param(id='reseller_customer_id', value=str(internal_tag)),
                Param(id='billing_date', value=str(subs_start))
            ]
            logger.info("End tier configuration for " + req.configuration.id)
            self.update_parameters(req.id, params)
            return ActivationTemplateResponse(partner_config['templates']['t1_template'])

        except FailRequest as err:
            self.__rollback()
            logger.error("Issue while processing Purchase request. Print Error: %s" % err)
            raise err
        except SkipRequest as err:
            logger.info(err)
            raise err
        except InquireRequest as err:
            self.__rollback()
            if self.tenant:
                self.service.remove(self.tenant)
            logger.error("Issue while processing Purchase request. Print Error: %s" % err)
            raise err
        except Exception as err:
            self.__rollback()
            if self.tenant:
                self.service.remove(self.tenant)
            logger.error("Issue while processing Purchase request. Print Error: %s" % err)
            raise err