コード例 #1
0
ファイル: instance.py プロジェクト: gbraad/ustack-gringotts
    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)
コード例 #2
0
ファイル: image.py プロジェクト: xiaolihope/gringotts
    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)
コード例 #3
0
ファイル: client.py プロジェクト: zhaozhilong1993/gringotts
    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))
コード例 #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)
コード例 #5
0
ファイル: client.py プロジェクト: ShooterTT/gringotts
    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))
コード例 #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)
コード例 #7
0
ファイル: floatingip.py プロジェクト: gbraad/ustack-gringotts
    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)
コード例 #8
0
ファイル: common.py プロジェクト: unitedstack/gringotts
    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()
        )
コード例 #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)
コード例 #10
0
ファイル: product.py プロジェクト: ShooterTT/gringotts
    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)
コード例 #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())
コード例 #12
0
ファイル: neutron.py プロジェクト: scorpioxiatian/gringotts
    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())
コード例 #13
0
ファイル: product.py プロジェクト: gbraad/ustack-gringotts
    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)
コード例 #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)
コード例 #15
0
ファイル: common.py プロジェクト: zhaozhilong1993/gringotts
    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)
コード例 #16
0
ファイル: gring_fixtures.py プロジェクト: ShooterTT/gringotts
    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)
コード例 #17
0
ファイル: product.py プロジェクト: gbraad/ustack-gringotts
    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)
コード例 #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)
コード例 #19
0
ファイル: service.py プロジェクト: unitedstack/gringotts
    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)
コード例 #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())
コード例 #21
0
ファイル: base.py プロジェクト: unitedstack/gringotts
    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())
コード例 #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
コード例 #23
0
ファイル: client.py プロジェクト: zhaozhilong1993/gringotts
    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)
コード例 #24
0
ファイル: context.py プロジェクト: ShooterTT/gringotts
def generate_request_id():
    return 'req-%s' % uuidutils.generate_uuid()
コード例 #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'])
コード例 #26
0
ファイル: client.py プロジェクト: ShooterTT/gringotts
    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)
コード例 #27
0
ファイル: context.py プロジェクト: zhaozhilong1993/gringotts
def generate_request_id():
    return 'req-%s' % uuidutils.generate_uuid()
コード例 #28
0
ファイル: bill.py プロジェクト: ShooterTT/gringotts
    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'])
コード例 #29
0
ファイル: correlation_id.py プロジェクト: ShooterTT/gringotts
 def process_request(self, req):
     correlation_id = (req.headers.get("X_CORRELATION_ID") or
                       uuidutils.generate_uuid())
     req.headers['X_CORRELATION_ID'] = correlation_id