Exemplo n.º 1
0
    def process_notification(self, message, state=None):
        LOG.warn("Do action for event: %s, resource_id: %s", message["event_type"], message["payload"]["instance_id"])

        # Generate uuid of an order
        order_id = uuidutils.generate_uuid()

        unit_price = 0
        unit = "hour"

        # Create subscriptions for this order
        for ext in self.product_items.extensions:
            # disk extension is used when instance been stopped and been suspend
            if ext.name.startswith("stopped"):
                sub = ext.obj.create_subscription(message, order_id, type=const.STATE_STOPPED)
                if sub and state == const.STATE_STOPPED:
                    p = gringutils._quantize_decimal(sub["unit_price"])
                    unit_price += p * sub["quantity"]
            elif ext.name.startswith("running"):
                sub = ext.obj.create_subscription(message, order_id, type=const.STATE_RUNNING)
                if sub and (not state or state == const.STATE_RUNNING):
                    p = gringutils._quantize_decimal(sub["unit_price"])
                    unit_price += p * sub["quantity"]

        # Create an order for this instance
        self.create_order(order_id, unit_price, unit, message, state=state)

        # Notify master
        remarks = "Instance Has Been Created."
        action_time = message["timestamp"]
        if state:
            self.resource_created_again(order_id, action_time, remarks)
            if state == const.STATE_STOPPED:
                self.instance_stopped(order_id, action_time)
        else:
            self.resource_created(order_id, action_time, remarks)
Exemplo n.º 2
0
    def process_notification(self, message, state=None):
        LOG.warn('Do action for event: %s, resource_id: %s',
                 message['event_type'], message['payload']['id'])

        # Generate uuid of an order
        order_id = uuidutils.generate_uuid()

        unit_price = 0
        unit = 'hour'

        # Create subscriptions for this order
        for ext in self.product_items.extensions:
            if ext.name.startswith('suspend'):
                sub = ext.obj.create_subscription(message, order_id,
                                                  type=const.STATE_SUSPEND)
                if sub and state==const.STATE_SUSPEND:
                    p = gringutils._quantize_decimal(sub['unit_price'])
                    unit_price += p * sub['quantity']
            elif ext.name.startswith('running'):
                sub = ext.obj.create_subscription(message, order_id,
                                                  type=const.STATE_RUNNING)
                if sub and (not state or state==const.STATE_RUNNING):
                    p = gringutils._quantize_decimal(sub['unit_price'])
                    unit_price += p * sub['quantity']

        # Create an order for this instance
        self.create_order(order_id, unit_price, unit, message, state=state)

        # Notify master
        remarks = 'Image Has Been Created.'
        action_time = message['timestamp']
        if state:
            self.resource_created_again(order_id, action_time, remarks)
        else:
            self.resource_created(order_id, action_time, remarks)
Exemplo n.º 3
0
    def create_deduct(self,
                      user_id,
                      money,
                      type="1",
                      remark=None,
                      req_id=None,
                      **kwargs):
        """Only create deduct record in database, not deduct account
        """
        req_id = req_id if req_id else uuidutils.generate_uuid()

        _body = dict(reqId=req_id,
                     accountNum=user_id,
                     money=money,
                     type=type,
                     remark=remark,
                     extData=kwargs,
                     deduct=False)

        failed = False

        try:
            __, body = self.client.put('/pay', body=_body)
            if str(body['code']) != "0":
                failed = True
        except Exception:
            failed = True

        if failed:
            LOG.warn("Fail to backup the deduct: user_id: %s, money: %s" %
                     (user_id, money))
Exemplo n.º 4
0
    def build_product_model(self,
                            name,
                            service,
                            description,
                            unit_price,
                            unit,
                            quantity=0,
                            extra=None,
                            product_id=None,
                            region_id=CONF.region_name,
                            type='regular',
                            deleted=False):

        if not product_id:
            product_id = uuidutils.generate_uuid()

        created_at = None
        updated_at = None
        deleted_at = None

        return db_models.Product(product_id=product_id,
                                 name=name,
                                 service=service,
                                 unit_price=unit_price,
                                 unit=unit,
                                 extra=extra,
                                 description=description,
                                 quantity=quantity,
                                 region_id=region_id,
                                 type=type,
                                 deleted=deleted,
                                 created_at=created_at,
                                 updated_at=updated_at,
                                 deleted_at=deleted_at)
Exemplo n.º 5
0
    def create_deduct(self, user_id, money, type="1", remark=None, req_id=None,
                      **kwargs):
        """Only create deduct record in database, not deduct account
        """
        req_id = req_id if req_id else uuidutils.generate_uuid()

        _body = dict(reqId=req_id,
                     accountNum=user_id,
                     money=money,
                     type=type,
                     remark=remark,
                     extData=kwargs,
                     deduct=False)

        failed = False

        try:
            __, body = self.client.put('/pay', body=_body)
            if str(body['code']) != "0":
                failed = True
        except Exception:
            failed = True

        if failed:
            LOG.warn("Fail to backup the deduct: user_id: %s, money: %s" %
                     (user_id, money))
Exemplo n.º 6
0
    def process_notification(self, message, state=None):
        payload = get_payload(message)
        LOG.warn('Do action for event: %s, resource_id: %s',
                 message['event_type'], payload['id'])

        self.send_email_notification(message)

        # Generate uuid of an order
        order_id = uuidutils.generate_uuid()

        unit_price = 0
        unit = 'hour'

        # Create subscriptions for this order
        for ext in self.product_items.extensions:
            if ext.name.startswith('suspend'):
                sub = ext.obj.create_subscription(message, order_id,
                                                  type=const.STATE_SUSPEND)
                if sub and state == const.STATE_SUSPEND:
                    price_data = None
                    if 'extra' in sub and sub['extra']:
                        try:
                            extra_data = jsonutils.loads(sub['extra'])
                            price_data = extra_data.get('price', None)
                        except (Exception):
                            LOG.warning('Decode subscription["extra"] failed')

                    unit_price += pricing.calculate_price(
                        sub['quantity'], sub['unit_price'], price_data)
            elif ext.name.startswith('running'):
                sub = ext.obj.create_subscription(message, order_id,
                                                  type=const.STATE_RUNNING)
                if sub and (not state or state == const.STATE_RUNNING):
                    price_data = None
                    if 'extra' in sub and sub['extra']:
                        try:
                            extra_data = jsonutils.loads(sub['extra'])
                            price_data = extra_data.get('price', None)
                        except (Exception):
                            LOG.warning('Decode subscription["extra"] failed')

                    unit_price += pricing.calculate_price(
                        sub['quantity'], sub['unit_price'], price_data)

        # Create an order for this instance
        self.create_order(order_id, unit_price, unit, message, state=state)

        # Notify master, just give master messages it needs
        remarks = 'Floating IP Has Been Created.'
        action_time = message['timestamp']
        if state:
            self.resource_created_again(order_id, action_time, remarks)
        else:
            self.resource_created(order_id, action_time, remarks)
Exemplo n.º 7
0
    def process_notification(self, message, state=None):
        payload = get_payload(message)
        LOG.warn('Do action for event: %s, resource_id: %s',
                 message['event_type'], payload['id'])

        self.send_email_notification(message)

        # Generate uuid of an order
        order_id = uuidutils.generate_uuid()

        unit_price = 0
        unit = 'hour'

        # Create subscriptions for this order
        for ext in self.product_items.extensions:
            if ext.name.startswith('suspend'):
                sub = ext.obj.create_subscription(message, order_id,
                                                  type=const.STATE_SUSPEND)
                if sub and state == const.STATE_SUSPEND:
                    price_data = None
                    if 'extra' in sub and sub['extra']:
                        try:
                            extra_data = jsonutils.loads(sub['extra'])
                            price_data = extra_data.get('price', None)
                        except (Exception):
                            LOG.warning('Decode subscription["extra"] failed')

                    unit_price += pricing.calculate_price(
                        sub['quantity'], sub['unit_price'], price_data)
            elif ext.name.startswith('running'):
                sub = ext.obj.create_subscription(message, order_id,
                                                  type=const.STATE_RUNNING)
                if sub and (not state or state == const.STATE_RUNNING):
                    price_data = None
                    if 'extra' in sub and sub['extra']:
                        try:
                            extra_data = jsonutils.loads(sub['extra'])
                            price_data = extra_data.get('price', None)
                        except (Exception):
                            LOG.warning('Decode subscription["extra"] failed')

                    unit_price += pricing.calculate_price(
                        sub['quantity'], sub['unit_price'], price_data)

        # Create an order for this instance
        self.create_order(order_id, unit_price, unit, message, state=state)

        # Notify master, just give master messages it needs
        remarks = 'Floating IP Has Been Created.'
        action_time = message['timestamp']
        if state:
            self.resource_created_again(order_id, action_time, remarks)
        else:
            self.resource_created(order_id, action_time, remarks)
Exemplo n.º 8
0
    def create_order(self, resource, unit="hour", period=None, renew=None):
        """Create order for resource. """
        order_id = uuidutils.generate_uuid()
        parsed_resource = self.parse_resource(resource)
        unit_price = self.get_unit_price(resource, method=unit)

        for ext in self.product_items.extensions:
            state = ext.name.split("_")[0]
            ext.obj.create_subscription(resource.to_env(), resource.to_body(), order_id, type=state)

        GCLIENT.create_order(
            order_id, CONF.region_name, unit_price, unit, period=period, renew=renew, **parsed_resource.as_dict()
        )
Exemplo n.º 9
0
    def post(self, data):
        """Create a new product."""
        data.product_id = uuidutils.generate_uuid()
        conn = pecan.request.db_conn

        # API model to DB model
        try:
            product_in = db_models.Product(deleted=False, **data.as_dict())
        except Exception:
            error = 'Error while turning product: %s' % data.as_dict()
            LOG.exception(error)
            raise exception.MissingRequiredParams(reason=error)

        # Check and process unit_price data
        if product_in.unit_price is not None:
            price_data = ProductExtraData(product_in.unit_price.as_dict())
            price_data.validate()

        # Check if there are duplicated name in the same region
        filters = {
            'name': data.name,
            'service': data.service,
            'region_id': data.region_id
        }

        products = list(conn.get_products(request.context, filters=filters))

        if len(products) > 0:
            error = "Product with name(%s) within service(%s) already "\
                    "exists in region_id(%s)" % \
                    (data.name, data.service, data.region_id)
            LOG.warning(error)
            raise exception.DuplicatedProduct(reason=error)

        # Write product model to DB
        try:
            product = conn.create_product(request.context, product_in)
        except Exception:
            error = 'Error while creating product: %s' % data.as_dict()
            LOG.exception(error)
            raise exception.DBError(reason=error)

        # DB model to API model
        return models.Product(product_id=product.product_id,
                              name=product.name,
                              service=product.service,
                              region_id=product.region_id,
                              description=product.description,
                              unit_price=product_in.unit_price,
                              created_at=product.created_at,
                              updated_at=product.updated_at)
Exemplo n.º 10
0
    def post(self, data):
        """Create a new product."""
        data.product_id = uuidutils.generate_uuid()
        conn = pecan.request.db_conn

        # API model to DB model
        try:
            product_in = db_models.Product(deleted=False,
                                           **data.as_dict())
        except Exception:
            error = 'Error while turning product: %s' % data.as_dict()
            LOG.exception(error)
            raise exception.MissingRequiredParams(reason=error)

        # Check and process unit_price data
        if product_in.unit_price is not None:
            price_data = ProductExtraData(product_in.unit_price.as_dict())
            price_data.validate()

        # Check if there are duplicated name in the same region
        filters = {'name': data.name,
                   'service': data.service,
                   'region_id': data.region_id}

        products = list(conn.get_products(request.context, filters=filters))

        if len(products) > 0:
            error = "Product with name(%s) within service(%s) already "\
                    "exists in region_id(%s)" % \
                    (data.name, data.service, data.region_id)
            LOG.warning(error)
            raise exception.DuplicatedProduct(reason=error)

        # Write product model to DB
        try:
            product = conn.create_product(request.context, product_in)
        except Exception:
            error = 'Error while creating product: %s' % data.as_dict()
            LOG.exception(error)
            raise exception.DBError(reason=error)

        # DB model to API model
        return models.Product(product_id=product.product_id,
                              name=product.name,
                              service=product.service,
                              region_id=product.region_id,
                              description=product.description,
                              unit_price=product_in.unit_price,
                              created_at=product.created_at,
                              updated_at=product.updated_at)
Exemplo n.º 11
0
    def create_order(self, env, start_response, body, unit_price, unit, period,
                     renew, resource):
        order_id = uuidutils.generate_uuid()

        for ext in self.product_items[resource.type].extensions:
            state = ext.name.split('_')[0]
            ext.obj.create_subscription(env, body, order_id, type=state)
        self.gclient.create_order(order_id,
                                  cfg.CONF.billing.region_name,
                                  unit_price,
                                  unit,
                                  period=period,
                                  renew=renew,
                                  **resource.as_dict())
Exemplo n.º 12
0
    def create_order(self, env, start_response, body,
                     unit_price, unit, period, renew, resource):
        order_id = uuidutils.generate_uuid()

        for ext in self.product_items[resource.type].extensions:
            state = ext.name.split('_')[0]
            ext.obj.create_subscription(env, body, order_id, type=state)
        self.gclient.create_order(order_id,
                                  cfg.CONF.billing.region_name,
                                  unit_price,
                                  unit,
                                  period=period,
                                  renew=renew,
                                  **resource.as_dict())
Exemplo n.º 13
0
    def post(self, data):
        """Create a new product."""
        data.product_id = uuidutils.generate_uuid()
        conn = pecan.request.db_conn

        # API model to DB model
        try:
            product_in = db_models.Product(quantity=0, deleted=False, **data.as_dict())
        except Exception:
            error = "Error while turning product: %s" % data.as_dict()
            LOG.exception(error)
            raise exception.MissingRequiredParams(reason=error)

        # Check and process extra data
        if product_in.extra is not None:
            extra_data = ProductExtraData(product_in.extra)
            new_extra_data = extra_data.validate()
            product_in.extra = new_extra_data

        # Check if there are duplicated name in the same region
        filters = {"name": data.name, "service": data.service, "region_id": data.region_id}

        products = list(conn.get_products(request.context, filters=filters))

        if len(products) > 0:
            error = "Product with name(%s) within service(%s) already " "exists in region_id(%s)" % (
                data.name,
                data.service,
                data.region_id,
            )
            LOG.warning(error)
            raise exception.DuplicatedProduct(reason=error)

        # Write product model to DB
        try:
            product = conn.create_product(request.context, product_in)
        except Exception:
            error = "Error while creating product: %s" % data.as_dict()
            LOG.exception(error)
            raise exception.DBError(reason=error)

        product.unit_price = quantize_decimal(product.unit_price)

        # DB model to API model
        return models.Product.from_db_model(product)
Exemplo n.º 14
0
    def post(self, data):
        """Create a new product
        """
        data.product_id = uuidutils.generate_uuid()
        conn = pecan.request.db_conn

        # API model to DB model
        try:
            product_in = db_models.Product(quantity=0,
                                           deleted=False,
                                           **data.as_dict())
        except Exception as e:
            error = 'Error while turning product: %s' % data.as_dict()
            LOG.exception(error)
            raise exception.MissingRequiredParams(reason=error)

        # Check if there are duplicated name in the same region
        filters = {
            'name': data.name,
            'service': data.service,
            'region_id': data.region_id
        }

        products = list(conn.get_products(request.context, filters=filters))

        if len(products) > 0:
            error = "Product with name(%s) within service(%s) already "\
                    "exists in region_id(%s)" % \
                    (data.name, data.service, data.region_id)
            LOG.warning(error)
            raise exception.DuplicatedProduct(reason=error)

        # Write product model to DB
        try:
            product = conn.create_product(request.context, product_in)
        except Exception as e:
            error = 'Error while creating product: %s' % data.as_dict()
            LOG.exception(error)
            raise exception.DBError(reason=error)

        product.unit_price = gringutils._quantize_decimal(product.unit_price)

        # DB model to API model
        return models.Product.from_db_model(product)
Exemplo n.º 15
0
    def create_order(self, resource, unit='hour', period=None, renew=None):
        """Create order for resource. """
        order_id = uuidutils.generate_uuid()
        parsed_resource = self.parse_resource(resource)
        unit_price = self.get_unit_price(resource, method=unit)

        for ext in self.product_items[resource.resource_type].extensions:
            state = ext.name.split('_')[0]
            ext.obj.create_subscription(resource.to_env(),
                                        resource.to_body(),
                                        order_id,
                                        type=state)

        GCLIENT.create_order(order_id,
                             CONF.region_name,
                             unit_price,
                             period=period,
                             renew=renew,
                             **parsed_resource.as_dict)
Exemplo n.º 16
0
    def build_product_model(self, name, service, description, unit_price,
                            unit, quantity=0, extra=None, product_id=None,
                            region_id=CONF.region_name, type='regular',
                            deleted=False):

        if not product_id:
            product_id = uuidutils.generate_uuid()

        created_at = None
        updated_at = None
        deleted_at = None

        return db_models.Product(
            product_id=product_id, name=name, service=service,
            unit_price=unit_price, unit=unit, extra=extra,
            description=description, quantity=quantity,
            region_id=region_id, type=type, deleted=deleted,
            created_at=created_at, updated_at=updated_at,
            deleted_at=deleted_at)
Exemplo n.º 17
0
    def post(self, data):
        """Create a new product
        """
        data.product_id = uuidutils.generate_uuid()
        conn = pecan.request.db_conn

        # API model to DB model
        try:
            product_in = db_models.Product(quantity=0,
                                           deleted=False,
                                           **data.as_dict())
        except Exception as e:
            error = 'Error while turning product: %s' % data.as_dict()
            LOG.exception(error)
            raise exception.MissingRequiredParams(reason=error)

        # Check if there are duplicated name in the same region
        filters = {'name': data.name,
                   'service': data.service,
                   'region_id': data.region_id}

        products = list(conn.get_products(request.context, filters=filters))

        if len(products) > 0:
            error = "Product with name(%s) within service(%s) already "\
                    "exists in region_id(%s)" % \
                    (data.name, data.service, data.region_id)
            LOG.warning(error)
            raise exception.DuplicatedProduct(reason=error)

        # Write product model to DB
        try:
            product = conn.create_product(request.context, product_in)
        except Exception as e:
            error = 'Error while creating product: %s' % data.as_dict()
            LOG.exception(error)
            raise exception.DBError(reason=error)

        product.unit_price = gringutils._quantize_decimal(product.unit_price)

        # DB model to API model
        return models.Product.from_db_model(product)
Exemplo n.º 18
0
    def start(self):
        super(CheckerService, self).start()
        # NOTE(suo): We should create coordinator and member_id in start(),
        # because child process will execute start() privately, thus every
        # child process will have its own coordination connection.
        self.member_id = uuidutils.generate_uuid()
        self.partition_coordinator = coordination.PartitionCoordinator(
            self.member_id)
        self.partition_coordinator.start()
        self.partition_coordinator.join_group(self.PARTITIONING_GROUP_NAME)

        if self.partition_coordinator.is_active():
            # NOTE(suo): Don't use loopingcall to do heartbeat, it will hang
            # if tooz driver restarts
            self.apsched.add_job(self.partition_coordinator.heartbeat,
                                 'interval',
                                 seconds=cfg.CONF.coordination.heartbeat)

        # NOTE(suo): apscheduler must be started in child process
        self.apsched.start()
        self.load_jobs()
        self.tg.add_timer(604800, lambda: None)
Exemplo n.º 19
0
    def start(self):
        super(CheckerService, self).start()
        # NOTE(suo): We should create coordinator and member_id in start(),
        # because child process will execute start() privately, thus every
        # child process will have its own coordination connection.
        self.member_id = uuidutils.generate_uuid()
        self.partition_coordinator = coordination.PartitionCoordinator(
            self.member_id)
        self.partition_coordinator.start()
        self.partition_coordinator.join_group(self.PARTITIONING_GROUP_NAME)

        if self.partition_coordinator.is_active():
            # NOTE(suo): Don't use loopingcall to do heartbeat, it will hang
            # if tooz driver restarts
            self.apsched.add_job(self.partition_coordinator.heartbeat,
                                 'interval',
                                 seconds=cfg.CONF.coordination.heartbeat)

        # NOTE(suo): apscheduler must be started in child process
        self.apsched.start()
        self.load_jobs()
        self.tg.add_timer(604800, lambda: None)
Exemplo n.º 20
0
    def create_order(self, env, start_response, body, unit_price, unit, period,
                     renew, resource):
        """Create an order for resource created

        1. Create subscriptions of this order
        2. Create order, can create cron job in the request
           create order
        """
        order_id = uuidutils.generate_uuid()

        # Create subscriptions for this order
        for ext in self.product_items.extensions:
            state = ext.name.split('_')[0]
            ext.obj.create_subscription(env, body, order_id, type=state)

        self.gclient.create_order(order_id,
                                  cfg.CONF.billing.region_name,
                                  unit_price,
                                  unit,
                                  period=period,
                                  renew=renew,
                                  **resource.as_dict())
Exemplo n.º 21
0
    def create_order(self, env, start_response, body,
                     unit_price, unit, period, renew, resource):
        """Create an order for resource created

        1. Create subscriptions of this order
        2. Create order, can create cron job in the request
           create order
        """
        order_id = uuidutils.generate_uuid()

        # Create subscriptions for this order
        for ext in self.product_items.extensions:
            state = ext.name.split('_')[0]
            ext.obj.create_subscription(env, body, order_id, type=state)

        self.gclient.create_order(order_id,
                                  cfg.CONF.billing.region_name,
                                  unit_price,
                                  unit,
                                  period=period,
                                  renew=renew,
                                  **resource.as_dict())
Exemplo n.º 22
0
 def process_request(self, req):
     correlation_id = (req.headers.get("X_CORRELATION_ID")
                       or uuidutils.generate_uuid())
     req.headers['X_CORRELATION_ID'] = correlation_id
Exemplo n.º 23
0
    def deduct_external_account(self,
                                user_id,
                                money,
                                type="1",
                                remark=None,
                                req_id=None,
                                **kwargs):
        """Deduct the account from external billing system

        if failed, will check the account was deducted successfully:
            if successfull:
                will return gracefully
            if failed:
                will deduct the account again
                if successfull:
                    return gracefully
                elif failed:
                    raise Exception
        elif successfull:
            will return gracefully
        """
        req_id = req_id if req_id else uuidutils.generate_uuid()

        _body = dict(reqId=req_id,
                     accountNum=user_id,
                     money=money,
                     type=type,
                     remark=remark,
                     extData=kwargs)

        failed = False
        retry = False

        # deduct first
        try:
            __, body = self.client.put('/pay', body=_body)
            if str(body['code']) != "0":
                failed = True
        except Exception:
            failed = True

        # check
        # if checking itself is failed, then we think the deduction is failed
        if failed:
            params = dict(reqId=req_id)
            try:
                __, body = self.client.get('/checkReq', params=params)
                if str(body['code']) != "0":
                    raise Exception
            except Exception:
                msg = "Check request account(%s) failed, deduct money(%s), \
                       req_id(%s), reason: %s"                                               % \
                    (user_id, money, req_id, body)
                LOG.exception(msg)
                raise exception.DeductError(user_id=user_id,
                                            money=money,
                                            req_id=req_id)
            if str(body['data'][0]['status']) != "0":
                retry = True

        # retry
        if retry:
            try:
                __, body = self.client.put('/pay', body=_body)
                if str(body['code']) != "0":
                    raise Exception
            except Exception:
                msg = "Deduct external account(%s) failed, deduct money(%s), \
                       req_id(%s), response: %s"                                                 % \
                    (user_id, money, req_id, body)
                LOG.exception(msg)
                raise exception.DeductError(user_id=user_id,
                                            money=money,
                                            req_id=req_id)
Exemplo n.º 24
0
def generate_request_id():
    return 'req-%s' % uuidutils.generate_uuid()
Exemplo n.º 25
0
    def post(self, data):
        """Create a bill

        Four steps to create a bill:
        1. get user_id via order_id
        2. get external account balance via user_id
        3. create a bill
        4. deduct external account

        If one of (1, 2, 3) step fails, just raise exception to stop the
        procedure, it will create this bill in next regular deducting circle.

        But if the 4th step fails, we should save the deducting record in our
        system to sync with the external system when it works again.
        """
        conn = pecan.request.db_conn
        external_balance = None
        ctxt = pecan.request.context

        try:
            if cfg.CONF.external_billing.enable:
                # 1. get user_id via order_id
                user_id = conn.get_order(ctxt, data.order_id).user_id

                # 2. get external account balance via user_id
                external_balance = self.external_client.get_external_balance(
                    user_id)['data'][0]['money']

            # 3. create bill
            result = conn.create_bill(ctxt,
                                      data['order_id'],
                                      action_time=data['action_time'],
                                      remarks=data['remarks'],
                                      end_time=data['end_time'],
                                      external_balance=external_balance)

            if cfg.CONF.external_billing.enable and result['type'] >= 0:
                # 4. deduct external account
                req_id = uuidutils.generate_uuid()
                extdata = dict(resource_id=result['resource_id'],
                               resource_name=result['resource_name'],
                               resource_type=result['resource_type'],
                               region_id=result['region_id'],
                               order_id=data.order_id)
                try:
                    self.external_client.deduct_external_account(
                        user_id,
                        str(result['deduct_value']),
                        type="1",
                        remark="come from ustack",
                        req_id=req_id,
                        **extdata)
                except Exception as e:
                    LOG.exception(
                        "Fail to deduct external account, "
                        "as reason: %s", e)
                    conn.deduct_account(ctxt,
                                        user_id,
                                        deduct=False,
                                        money=result['deduct_value'],
                                        reqId=req_id,
                                        type="1",
                                        remark="create bill backup",
                                        extData=extdata)
            LOG.debug('Create bill for order %s successfully.',
                      data['order_id'])
            return models.BillResult(**result)
        except Exception:
            LOG.exception('Fail to create bill for the order: %s',
                          data['order_id'])
            raise exception.BillCreateFailed(order_id=data['order_id'])
Exemplo n.º 26
0
    def deduct_external_account(self, user_id, money, type="1", remark=None,
                                req_id=None, **kwargs):
        """Deduct the account from external billing system

        if failed, will check the account was deducted successfully:
            if successfull:
                will return gracefully
            if failed:
                will deduct the account again
                if successfull:
                    return gracefully
                elif failed:
                    raise Exception
        elif successfull:
            will return gracefully
        """
        req_id = req_id if req_id else uuidutils.generate_uuid()

        _body = dict(reqId=req_id,
                     accountNum=user_id,
                     money=money,
                     type=type,
                     remark=remark,
                     extData=kwargs)

        failed = False
        retry = False

        # deduct first
        try:
            __, body = self.client.put('/pay', body=_body)
            if str(body['code']) != "0":
                failed = True
        except Exception:
            failed = True

        # check
        # if checking itself is failed, then we think the deduction is failed
        if failed:
            params = dict(reqId=req_id)
            try:
                __, body = self.client.get('/checkReq', params=params)
                if str(body['code']) != "0":
                    raise Exception
            except Exception:
                msg = "Check request account(%s) failed, deduct money(%s), \
                       req_id(%s), reason: %s" % \
                    (user_id, money, req_id, body)
                LOG.exception(msg)
                raise exception.DeductError(user_id=user_id,
                                            money=money,
                                            req_id=req_id)
            if str(body['data'][0]['status']) != "0":
                retry = True

        # retry
        if retry:
            try:
                __, body = self.client.put('/pay', body=_body)
                if str(body['code']) != "0":
                    raise Exception
            except Exception:
                msg = "Deduct external account(%s) failed, deduct money(%s), \
                       req_id(%s), response: %s" % \
                    (user_id, money, req_id, body)
                LOG.exception(msg)
                raise exception.DeductError(user_id=user_id,
                                            money=money,
                                            req_id=req_id)
Exemplo n.º 27
0
def generate_request_id():
    return 'req-%s' % uuidutils.generate_uuid()
Exemplo n.º 28
0
    def post(self, data):
        """Create a bill

        Four steps to create a bill:
        1. get user_id via order_id
        2. get external account balance via user_id
        3. create a bill
        4. deduct external account

        If one of (1, 2, 3) step fails, just raise exception to stop the
        procedure, it will create this bill in next regular deducting circle.

        But if the 4th step fails, we should save the deducting record in our
        system to sync with the external system when it works again.
        """
        conn = pecan.request.db_conn
        external_balance = None
        ctxt = pecan.request.context

        try:
            if cfg.CONF.external_billing.enable:
                # 1. get user_id via order_id
                user_id = conn.get_order(ctxt, data.order_id).user_id

                # 2. get external account balance via user_id
                external_balance = self.external_client.get_external_balance(
                    user_id)['data'][0]['money']

            # 3. create bill
            result = conn.create_bill(ctxt, data['order_id'],
                                      action_time=data['action_time'],
                                      remarks=data['remarks'],
                                      end_time=data['end_time'],
                                      external_balance=external_balance)

            if cfg.CONF.external_billing.enable and result['type'] >= 0:
                # 4. deduct external account
                req_id = uuidutils.generate_uuid()
                extdata = dict(resource_id=result['resource_id'],
                               resource_name=result['resource_name'],
                               resource_type=result['resource_type'],
                               region_id=result['region_id'],
                               order_id=data.order_id)
                try:
                    self.external_client.deduct_external_account(
                        user_id,
                        str(result['deduct_value']),
                        type="1",
                        remark="come from ustack",
                        req_id=req_id,
                        **extdata)
                except Exception as e:
                    LOG.exception("Fail to deduct external account, "
                                  "as reason: %s", e)
                    conn.deduct_account(ctxt, user_id, deduct=False,
                                        money=result['deduct_value'],
                                        reqId=req_id,
                                        type="1",
                                        remark="create bill backup",
                                        extData=extdata)
            LOG.debug('Create bill for order %s successfully.',
                      data['order_id'])
            return models.BillResult(**result)
        except Exception:
            LOG.exception('Fail to create bill for the order: %s',
                          data['order_id'])
            raise exception.BillCreateFailed(order_id=data['order_id'])
Exemplo n.º 29
0
 def process_request(self, req):
     correlation_id = (req.headers.get("X_CORRELATION_ID") or
                       uuidutils.generate_uuid())
     req.headers['X_CORRELATION_ID'] = correlation_id