def report_user_usage(email): user = User.get_by_email(email) if not user: raise exceptions.UserNotFoundException(email) for application in user.application_set.all(): changes = AllocationChange.objects.filter( application=application).filter(billed=False) if changes.count() < 1: continue log_info_message("for application %s, reporting %s changes" % (application, changes.count())) for chargable in Chargable.objects.all(): total_seconds = 0.0 total_cents = 0.0 # only look at allocs from before one minute ago now = datetime.datetime.now() - datetime.timedelta(seconds=60) allocs = list( changes.filter(chargable=chargable).filter( timestamp__lt=now).order_by('-timestamp')) if len(allocs) < 1: continue latest = allocs[-1] latest_copy = AllocationChange(application=application, chargable=chargable, quantity=latest.quantity, timestamp=now) latest_copy.save() allocs.insert(0, latest_copy) for alloc in allocs: if alloc == latest_copy: continue diff = (now - alloc.timestamp).seconds if chargable.component == Chargable.components[ 'application_processes']: # the (alloc.quantity - 1) is to ensure the first process is free price = (diff * (alloc.quantity - 1) * (chargable.price / 3600.0)) else: price = (diff * (alloc.quantity) * (chargable.price / 3600.0)) total_cents += price total_seconds += diff now = alloc.timestamp alloc.billed = True total_hours = (total_seconds / 3600) + 1 result = report_usage(user, total_cents, memo="%s hours for %s" % (total_hours, chargable)) if result: [alloc.save() for alloc in allocs] be = BillingEvent(email=email, customer_id=user.customer_id, application_name=application.name, chargable_name=str(chargable), cents=total_cents, success=True, memo="devpayments dump: %s" % str(result)) be.save() log_info_message( "Reported %s cents for %s for application %s" % (total_cents, chargable, application.name)) else: be = BillingEvent(email=email, customer_id=user.customer_id, application_name=application.name, chargable_name=str(chargable), cents=total_cents, success=False, memo="devpayments dump: %s" % str(result)) be.save() log_error_message( "Reporting failed for %s cents for %s for application %s: %s" % (total_cents, chargable, application.name, result))
def update_billing_info(email, info): def _unpack_customer_info(): return { 'first_name': info.get('first_name', ''), 'last_name': info.get('last_name', ''), 'email': email } def _unpack_billing_info(): return { 'number': info['cc_number'], 'exp_month': info['expiration_month'], 'exp_year': info['expiration_year'], 'cvc': info['cvv'] } def _create_new_customer(): devpay = devpayments.Client(DEVPAYMENTS_API_KEY) try: result = devpay.createCustomer( mnemonic=_unpack_customer_info()['email'], card=_unpack_billing_info()) user.customer_id = result.id user.save() except DevPayException as e: return e.message return True def _update_customer(): devpay = devpayments.Client(DEVPAYMENTS_API_KEY) try: result = devpay.updateCustomer( id=user.customer_id, mnemonic=_unpack_customer_info()['email'], card=_unpack_billing_info()) user.customer_id = result.id user.save() except DevPayException as e: return e.message return True user = User.get_by_email(email) if not user: raise exceptions.UserNotFoundException(email) message = True if user.customer_id == '-1' or user.customer_id == '': try: result = _create_new_customer() if True != result: message = result except Exception as e: log_error_message(e) return "Our system encountered an error. Please contact [email protected]." else: try: result = _update_customer() if True != result: message = result except Exception as e: log_error_message(e) return "Our system encountered an error. Please contact [email protected]." try: cust_info = _unpack_customer_info() user.first_name = cust_info.get('first_name', '') user.last_name = cust_info.get('last_name', '') user.save() except Exception as e: log_error_message(e) return "Our system encountered an error. Please contact [email protected]." return message
def add_application(application_name, email, pubkey): """ Add the application specified by application_name and a corresponding database, owned by the user with the email address specified. """ # Claim the application name ActiveApplicationName(name=application_name).save() user = User.get_by_email(email) # generate a secure password db_password = gen_password() # create the application row app = Application() app.name = application_name app.account = user app.db_name = application_name app.db_username = application_name app.db_password = db_password app.db_host = DEFAULT_DATABASE_HOST app.num_procs = 1 app.save() # generate user and group ids to run as uids_gid = gen_uids_gid(app.id) app.setup_uid = uids_gid['setup_uid'] app.web_uid = uids_gid['web_uid'] app.cron_uid = uids_gid['cron_uid'] app.app_gid = uids_gid['app_gid'] app.save() # enable git push create_git_repository(application_name) add_ssh_public_key(user, pubkey) # allocate a proxycache host for the application -- improve on this later ProxyCache(application = app, host = DEFAULT_PROXYCACHE_HOST).save() # assign virtualhost on which to listen for application VirtualHost(application = app, virtualhost = application_name + '.djangy.com').save() # allocate the application to a worker host # Note: this must happen after ProxyCache and VirtualHost are filled in. allocate_workers(app) # create the database db = _mysql.connect( host = DEFAULT_DATABASE_HOST, user = DATABASE_ROOT_USER, passwd = DATABASE_ROOT_PASSWORD) try: # try to remove the user if it already exists db.query(""" DROP USER '%s'@'%%';""" % application_name) except: pass db.query(""" CREATE USER '%s'@'%%' IDENTIFIED BY '%s';""" % (application_name, db_password)) try: # try to drop the database in case it exists db.query(""" DROP DATABASE %s;""" % application_name) except: pass db.query(""" CREATE DATABASE %s;""" % application_name) db.query(""" USE %s""" % application_name) db.query(""" GRANT ALL ON %s.* TO '%s'@'%%';""" % (application_name, application_name)) return True
def report_user_usage(email): user = User.get_by_email(email) if not user: raise exceptions.UserNotFoundException(email) for application in user.application_set.all(): changes = AllocationChange.objects.filter(application=application).filter(billed=False) if changes.count() < 1: continue log_info_message("for application %s, reporting %s changes" % (application, changes.count())) for chargable in Chargable.objects.all(): total_seconds = 0.0 total_cents = 0.0 # only look at allocs from before one minute ago now = datetime.datetime.now() - datetime.timedelta(seconds=60) allocs = list(changes.filter(chargable=chargable).filter(timestamp__lt=now).order_by('-timestamp')) if len(allocs) < 1: continue latest = allocs[-1] latest_copy = AllocationChange(application = application, chargable = chargable, quantity = latest.quantity, timestamp = now) latest_copy.save() allocs.insert(0, latest_copy) for alloc in allocs: if alloc == latest_copy: continue diff = (now - alloc.timestamp).seconds if chargable.component == Chargable.components['application_processes']: # the (alloc.quantity - 1) is to ensure the first process is free price = (diff * (alloc.quantity - 1) * (chargable.price / 3600.0)) else: price = (diff * (alloc.quantity) * (chargable.price / 3600.0)) total_cents += price total_seconds += diff now = alloc.timestamp alloc.billed = True total_hours = (total_seconds / 3600) + 1 result = report_usage(user, total_cents, memo="%s hours for %s" % (total_hours, chargable)) if result: [alloc.save() for alloc in allocs] be = BillingEvent( email = email, customer_id = user.customer_id, application_name = application.name, chargable_name = str(chargable), cents = total_cents, success = True, memo = "devpayments dump: %s" % str(result) ) be.save() log_info_message("Reported %s cents for %s for application %s" % (total_cents, chargable, application.name)) else: be = BillingEvent( email = email, customer_id = user.customer_id, application_name = application.name, chargable_name = str(chargable), cents = total_cents, success = False, memo = "devpayments dump: %s" % str(result) ) be.save() log_error_message("Reporting failed for %s cents for %s for application %s: %s" % (total_cents, chargable, application.name, result))
def update_billing_info(email, info): def _unpack_customer_info(): return { 'first_name':info.get('first_name', ''), 'last_name':info.get('last_name', ''), 'email':email } def _unpack_billing_info(): return { 'number':info['cc_number'], 'exp_month':info['expiration_month'], 'exp_year':info['expiration_year'], 'cvc':info['cvv'] } def _create_new_customer(): devpay = devpayments.Client(DEVPAYMENTS_API_KEY) try: result = devpay.createCustomer( mnemonic = _unpack_customer_info()['email'], card = _unpack_billing_info() ) user.customer_id = result.id user.save() except DevPayException as e: return e.message return True def _update_customer(): devpay = devpayments.Client(DEVPAYMENTS_API_KEY) try: result = devpay.updateCustomer( id = user.customer_id, mnemonic = _unpack_customer_info()['email'], card = _unpack_billing_info() ) user.customer_id = result.id user.save() except DevPayException as e: return e.message return True user = User.get_by_email(email) if not user: raise exceptions.UserNotFoundException(email) message = True if user.customer_id == '-1' or user.customer_id == '': try: result = _create_new_customer() if True != result: message = result except Exception as e: log_error_message(e) return "Our system encountered an error. Please contact [email protected]." else: try: result = _update_customer() if True != result: message = result except Exception as e: log_error_message(e) return "Our system encountered an error. Please contact [email protected]." try: cust_info = _unpack_customer_info() user.first_name = cust_info.get('first_name', '') user.last_name = cust_info.get('last_name', '') user.save() except Exception as e: log_error_message(e) return "Our system encountered an error. Please contact [email protected]." return message
def add_application(application_name, email, pubkey): """ Add the application specified by application_name and a corresponding database, owned by the user with the email address specified. """ # Claim the application name ActiveApplicationName(name=application_name).save() user = User.get_by_email(email) # generate a secure password db_password = gen_password() # create the application row app = Application() app.name = application_name app.account = user app.db_name = application_name app.db_username = application_name app.db_password = db_password app.db_host = DEFAULT_DATABASE_HOST app.num_procs = 1 app.save() # generate user and group ids to run as uids_gid = gen_uids_gid(app.id) app.setup_uid = uids_gid['setup_uid'] app.web_uid = uids_gid['web_uid'] app.cron_uid = uids_gid['cron_uid'] app.app_gid = uids_gid['app_gid'] app.save() # enable git push create_git_repository(application_name) add_ssh_public_key(user, pubkey) # allocate a proxycache host for the application -- improve on this later ProxyCache(application=app, host=DEFAULT_PROXYCACHE_HOST).save() # assign virtualhost on which to listen for application VirtualHost(application=app, virtualhost=application_name + '.djangy.com').save() # allocate the application to a worker host # Note: this must happen after ProxyCache and VirtualHost are filled in. allocate_workers(app) # create the database db = _mysql.connect(host=DEFAULT_DATABASE_HOST, user=DATABASE_ROOT_USER, passwd=DATABASE_ROOT_PASSWORD) try: # try to remove the user if it already exists db.query(""" DROP USER '%s'@'%%';""" % application_name) except: pass db.query(""" CREATE USER '%s'@'%%' IDENTIFIED BY '%s';""" % (application_name, db_password)) try: # try to drop the database in case it exists db.query(""" DROP DATABASE %s;""" % application_name) except: pass db.query(""" CREATE DATABASE %s;""" % application_name) db.query(""" USE %s""" % application_name) db.query(""" GRANT ALL ON %s.* TO '%s'@'%%';""" % (application_name, application_name)) return True