Commit 6c70e2d5 authored by David Seaward's avatar David Seaward

add subscription tasks, add legacy task (to flush queue)

parent f0240888
# import django.contrib.auth
# import paramiko
# from celery import shared_task
# from celery.utils.log import get_task_logger
# from django.conf import settings
# from django.db import transaction
# from django.utils import timezone
# from woocommerce import API as WOO_API
#
# from limitmonitor.models import ExternalCredit, ExternalBundle, Limit
#
# logger = get_task_logger(__name__)
#
#
# def get_woo_connection():
#
# return WOO_API(
# url=settings.WOO_URL,
# consumer_key=settings.WOO_CONSUMER_KEY,
# consumer_secret=settings.WOO_CONSUMER_SECRET,
# wp_api=settings.WOO_WP_API,
# version=settings.WOO_VERSION,
# )
#
#
# def get_openvpn_ssh_connection():
# # make ssh connection to OpenVPN server
# # (uses system host keys, warns if host is not recognised)
# ssh = paramiko.SSHClient()
# ssh.load_system_host_keys()
# ssh.set_missing_host_key_policy(paramiko.WarningPolicy()) # TODO: where is this logged?
# ssh.connect(
# hostname=settings.OVPN_HOSTNAME,
# port=settings.OVPN_PORT,
# username=settings.OVPN_USERNAME,
# )
#
# return ssh
#
#
# def managed_exec(ssh, command):
# stdin, stdout, stderr = ssh.exec_command(command)
#
# output = "".join(stdout.readlines()).strip()
# if output == "":
# output = "None."
#
# error = "".join(stderr.readlines()).strip()
#
# message = "Executed: %s Output: %s" % (command, output,)
#
# # on sucess, log output, otherwise raise exception
# if stdout.channel.recv_exit_status() == 0:
# logger.info(message)
# else:
# message += " Error: " + error
# raise Exception(message)
#
#
# def get_latest_woo1(connection, product_id):
# return connection.get("orders?product=" + str(product_id))
#
#
# def parse_woo1(json_entry, product_id):
# result_list = []
# order_name = json_entry["number"]
# order_id = json_entry["id"]
#
# for line_item in json_entry["line_items"]:
# if line_item["product_id"] == product_id:
#
# item_id = line_item["id"]
# product_id = line_item["product_id"]
# product_label = line_item["name"]
# quantity = line_item["quantity"]
#
# account = "invalid"
# for meta_item in line_item["meta"]:
# if meta_item["key"] in settings.WOO1_FIELD_LIST: # for example, "Existing username,"
# account = meta_item["value"]
#
# if account.count("@") == 0: # nodomain
# account += "@" + settings.SITE_DOMAIN # corrected to nodomain@example.com
# elif account.count("@") > 1: # bad@user@example.com
# raise Exception("Invalid username: " + account)
# elif not account.endswith(settings.SITE_DOMAIN): # user@unrecognised.com
# raise Exception("Bad username suffix: " + account)
#
# external_key = str(order_id) + ":" + str(item_id)
# external_label = order_name + ":" + str(item_id)
#
# result_list.append({
# "parser": "WOO1",
# "external_key": external_key,
# "label": external_label,
# "product_key": product_id,
# "product_label": product_label,
# "quantity": quantity,
# "account": account,
# "original_email": "",
# "isconverted": False,
# })
#
# return result_list
#
#
# def is_existing_credit(credit):
# matching_credits = ExternalCredit.objects.filter(
# parser=credit.parser,
# external_key=credit.external_key,
# )
#
# is_existing = len(matching_credits) > 0
#
# return is_existing
#
#
# def update_limit_woo1(ssh, credit):
# # validate credit
#
# suffix = "@" + settings.SITE_DOMAIN
# if credit.account_name is None or not str.endswith(credit.account_name, suffix):
# raise Exception("Invalid account name: " + str(credit.account_name))
# else:
# suffix_len = 0 - len(suffix)
# username = credit.account_name[:suffix_len]
#
# # get external references (implicit validation that they exist)
#
# external_bundle = ExternalBundle.objects.get(
# parser=credit.parser,
# external_key=credit.bundle_key,
# )
#
# limit = Limit.objects.get(
# user__username=username,
# service=external_bundle.service,
# )
#
# user = django.contrib.auth.get_user_model().objects.get(
# username=username,
# )
#
# # set user email if missing
# credit_has_email = not (credit.additional_data is None or credit.additional_data == "")
# user_has_email = not (user.email is None or user.email == "")
#
# if user_has_email:
# pass
# elif credit_has_email:
# user.email = credit.additional_data
# user.save()
# else:
# logger.warn("No email address for credit " + credit.parser + " " + credit.external_key)
#
# credit_days = int(external_bundle.time_credit * credit.quantity)
# credit_timedelta = timezone.timedelta(days=credit_days)
# activate(ssh, limit, credit_timedelta)
#
#
# def activate(ssh, limit, credit_timedelta):
#
# if limit.is_active:
# limit.expiry_date += credit_timedelta
# else:
# limit.expiry_date = timezone.now() + credit_timedelta
# limit.is_active = True
#
# if limit.service == "TUNNEL":
# managed_exec(ssh, "./create_new_ovpn_config --generate %s" % (limit.user.get_identity(),))
#
# limit.save()
#
#
# def deactivate(ssh, limit):
# if limit.service == "TUNNEL":
# managed_exec(ssh, "./create_new_ovpn_config --revoke %s" % (limit.user.get_identity(),))
#
# limit.is_active = False
# limit.save()
#
#
# @transaction.atomic
# def store_credit_and_update_limit(ssh, credit):
#
# try:
# if credit.parser == "WOO1":
# update_limit_woo1(ssh, credit)
# else:
# raise Exception("Unrecognised parser " + credit.parser)
#
# credit.is_converted = True
# credit.error_message = ""
# except Exception as e:
# message = "Skipped adding credit " + credit.parser + ":" + credit.external_key + ". "
# logger.exception(message)
# credit.error_message = message + repr(e)
# finally:
# credit.save()
# state = "converted" if credit.is_converted else "skipped"
# logger.info("Stored " + state + " credit " + credit.parser + ":" + credit.external_key)
#
#
# @shared_task
# def monitor_woo1():
# # make connection objects
# woo_connection = get_woo_connection()
# ssh = get_openvpn_ssh_connection()
#
# # get product sales and parse the results
# result_list = []
# for product_id in settings.WOO_PRODUCT_LIST:
# latest_woo1_json = get_latest_woo1(woo_connection, product_id).json()
# for json_entry in latest_woo1_json:
# try:
# result_list.extend(parse_woo1(json_entry, product_id))
# except Exception as e:
# logger.exception("Skipping JSON entry " + str(json_entry))
#
# # add new results
# count = 0
# for result in result_list:
# try:
#
# credit = ExternalCredit(
# parser=result["parser"],
# external_key=result["external_key"],
# label=result["label"],
# bundle_key=result["product_key"],
# bundle_label=result["product_label"],
# quantity=result["quantity"],
# account_name=result["account"],
# additional_data=result["original_email"],
# is_converted=False,
# )
#
# if not is_existing_credit(credit):
# store_credit_and_update_limit(ssh, credit)
# count += 1
# else:
# logger.debug("Skipped existing result " + str(result))
# except Exception as e:
# logger.exception("Skipped bad result " + str(result))
#
# if count > 0:
# logger.info("Added %i new results." % (count,))
#
# def parse_woosub1(json_entry):
#
# id = str(json_entry["id"])
# if len(json_entry["line_items"]) != 1:
# raise Exception("Too many line items in subscription %s" % (id, ))
#
# result = {}
# result["parser"] = "WOOSUB1"
# result["external_key"] = id + ":" + str(json_entry["line_items"][0]["product_id"])
# result["label"] = json_entry["line_items"][0]["name"]
#
#
# return
#
# @shared_task
# def monitor_woosub1_new_subscriptions():
# # make connection objects
# woo_connection = get_woo_connection()
# ssh = get_openvpn_ssh_connection()
#
# result_list = []
# latest_subscription_json = woo_connection.get("subscriptions?orderby=date&order=desc").json()
#
# # get product sales and parse the results
# for json_entry in latest_subscription_json:
# try:
# result_list.extend(parse_woosub1(json_entry))
# except Exception as e:
# logger.exception("Skipping JSON entry " + str(json_entry))
#
# # add new results
# count = 0
# for result in result_list:
# try:
#
# credit = ExternalCredit(
# parser=result["parser"],
# external_key=result["external_key"],
# label=result["label"],
# bundle_key=result["product_key"],
# bundle_label=result["product_label"],
# quantity=result["quantity"],
# account_name=result["account"],
# additional_data=None,
# is_converted=False,
# )
#
# if not is_existing_credit(credit):
# # store_woosub1_limit(ssh, credit, result["next_date"])
# count += 1
# else:
# logger.debug("Skipped existing result " + str(result))
# except Exception as e:
# logger.exception("Skipped bad result " + str(result))
#
# @shared_task
# def monitor_woosub1_renewals():
# # make connection objects
# woo_connection = get_woo_connection()
# ssh = get_openvpn_ssh_connection()
#
# # get objects due for renewal and deactivate them
# now = timezone.now()
# overdue_list = Limit.objects.filter(renewal_date__lte=now,expiry_date=None, is_active=True)
#
# for limit in overdue_list:
# woosub1_list = ExternalCredit.objects.filter(parser="WOOSUB1")
# for woosub in woosub1_list:
# subscription_query = "subscriptions/" + woosub.external_key
# woosub_json = woo_connection.get(subscription_query).json()
# result = parse_woosub1(woosub_json)
#
# if not result["active"]:
# deactivate(ssh, limit)
# else:
# woosub.updated_date = now
# limit.renewal_date = result["renewal"]
# limit.save()
#
# @shared_task
# def deactivate_all_expired_limits():
# # make connection objects
# ssh = get_openvpn_ssh_connection()
#
# # get overdue objects and deactivate them
# now = timezone.now()
# overdue_list = Limit.objects.filter(renewal_date=None,expiry_date__lte=now, is_active=True)
#
# for limit in overdue_list:
# deactivate(ssh, limit)
#
#
# @shared_task
# def debug_connection_task():
# # make connection objects
# woo_connection = get_woo_connection()
# ssh = get_openvpn_ssh_connection()
# managed_exec(ssh, "whoami")
#
# logger.info("Debug task with " + repr(woo_connection) + " and " + repr(ssh) + " completed successfully.")
import datetime
from .common import *
def parse_woosub1(json_entry):
subscription_id = str(json_entry["id"])
# validation
if len(json_entry["line_items"]) != 1:
raise Exception("Too many line items in subscription %s" % (id, ))
line_item = json_entry["line_items"][0]
quantity = line_item["quantity"]
if quantity != 1:
raise Exception("Bad quantity %s in subscription %s" % (quantity, id, ))
# calculate next renewal date
next_renewal_naive = datetime.datetime.strptime(json_entry["next_payment_date"], "%Y-%m-%dT%H:%M:%S")
next_renewal = timezone.make_aware(next_renewal_naive)
# create result
result = {
"parser": "WOOSUB1",
"external_key": subscription_id,
"label": json_entry["number"] + ":" + json_entry["order_key"],
"bundle_key": str(line_item["product_id"]),
"bundle_label": str(line_item["name"]),
"quantity": 1,
"account": get_account_from_woo_meta(line_item["meta"]),
"next_renewal": next_renewal,
}
return [result, ]
def monitor_woosub1_new_subscriptions():
# make connection objects
woo_connection = get_woo_connection()
ssh = get_openvpn_ssh_connection()
# initialise
result_list = []
latest_subscription_json = woo_connection.get("subscriptions?orderby=date&order=desc").json()
# parse recent subscriptions and store results
for json_entry in latest_subscription_json:
try:
result_list.extend(parse_woosub1(json_entry))
except Exception as e:
logger.exception("Skipping JSON entry " + str(json_entry))
# add new results
count = 0
for result in result_list:
try:
credit = ExternalCredit(
parser=result["parser"],
external_key=result["external_key"],
label=result["label"],
bundle_key=result["bundle_key"],
bundle_label=result["bundle_label"],
quantity=result["quantity"],
account_name=result["account"],
additional_data="None",
is_converted=False,
)
if not is_existing_credit(credit):
store_credit_and_update_limit(ssh, credit, result["next_renewal"])
count += 1
else:
logger.debug("Skipped existing result " + str(result))
except Exception as e:
logger.exception("Skipped bad result " + str(result))
def update_limit_woosub1(ssh, credit, renewal_date):
user, limit, external_bundle = get_limit_objects(credit)
activate(ssh, limit, None, renewal_date)
def monitor_woosub1_renewals():
return
# make connection objects
woo_connection = get_woo_connection()
ssh = get_openvpn_ssh_connection()
# get objects due for renewal and deactivate them
now = timezone.now()
overdue_list = Limit.objects.filter(renewal_date__lte=now,expiry_date=None, is_active=True)
for limit in overdue_list:
woosub1_list = ExternalCredit.objects.filter(parser="WOOSUB1")
for woosub in woosub1_list:
subscription_query = "subscriptions/" + woosub.external_key
woosub_json = woo_connection.get(subscription_query).json()
result = parse_woosub1(woosub_json)
if not result["active"]:
deactivate(ssh, limit)
else:
woosub.updated_date = now
limit.renewal_date = result["renewal"]
limit.save()
......@@ -7,12 +7,12 @@ from .task_resources import tunnel_subscription
@shared_task
def tunnel_refresh_subscription():
tunnel_subscription.do_nothing()
tunnel_subscription.monitor_woosub1_renewals()
@shared_task
def tunnel_new_subscription():
pass
tunnel_subscription.monitor_woosub1_new_subscriptions()
@shared_task
......@@ -28,3 +28,10 @@ def deactivate_all_expired_limits():
@shared_task
def debug_connection_task():
common.debug_connection_task()
@shared_task
def monitor_woo1():
# keep legacy task header so that it is flushed out of queue
# FIXME: this will be removed in the next release
pass
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment