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)
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)
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))
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)
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)
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() )
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)
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)
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())
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)
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)
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)
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)
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)
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)
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())
def process_request(self, req): correlation_id = (req.headers.get("X_CORRELATION_ID") or uuidutils.generate_uuid()) req.headers['X_CORRELATION_ID'] = correlation_id
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)
def generate_request_id(): return 'req-%s' % uuidutils.generate_uuid()
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'])
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'])