diff --git a/Changelog b/Changelog index d3c2c549..adc81a25 100644 --- a/Changelog +++ b/Changelog @@ -2,6 +2,8 @@ Next: * #3911: [dcl] Integrate resend activation link into dcl landing payment page * #3972: [hosting] Add ungleich company info to invoice footer * #3974: [hosting] Improve invoice number: Show 404 for invoice resources that do not belong to the user + * [ungleich] Add video cover to the header on ungleich.ch landing page and add corresponding cms plugin + * #3774: [hosting] |Update Stripe subscription on vm delete 1.2.13: 2017-12-09 * [cms] Introduce UngleichHeaderBackgroundImageAndTextSliderPlugin that allows to have scrolling images and texts * [cms] Remove
tag for ungleich cms customer item template diff --git a/hosting/views.py b/hosting/views.py index 70ca259e..576b3534 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -41,6 +41,7 @@ from utils.forms import ( from utils.hosting_utils import get_vm_price from utils.mailer import BaseEmail from utils.stripe_utils import StripeUtils +from utils.tasks import send_plain_email_task from utils.views import ( PasswordResetViewMixin, PasswordResetConfirmViewMixin, LoginViewMixin, ResendActivationLinkViewMixin @@ -1034,7 +1035,7 @@ class VirtualMachineView(LoginRequiredMixin, View): ) return None except Exception as error: - print(error) + logger.error(str(error)) raise Http404() def get_success_url(self): @@ -1077,49 +1078,88 @@ class VirtualMachineView(LoginRequiredMixin, View): def post(self, request, *args, **kwargs): response = {'status': False} + admin_email_body = {} owner = self.request.user vm = self.get_object() - opennebula_vm_id = self.kwargs.get('pk') - manager = OpenNebulaManager( email=owner.email, password=owner.password ) - try: vm_data = VirtualMachineSerializer(manager.get_vm(vm.id)).data vm_name = vm_data.get('name') - except WrongIdError: + except WrongIdError as wrong_id_err: + logger.error(str(wrong_id_err)) return redirect(reverse('hosting:virtual_machines')) + # Cancel Stripe subscription + stripe_utils = StripeUtils() + try: + hosting_order = HostingOrder.objects.get( + vm_id=vm.id + ) + result = stripe_utils.unsubscribe_customer( + subscription_id=hosting_order.subscription_id + ) + stripe_subscription_obj = result.get('response_object') + # Check if the subscription was canceled + if (stripe_subscription_obj is None or + stripe_subscription_obj.status != 'canceled'): + error_msg = result.get('error') + logger.error( + 'Error canceling subscription for {user} and vm id ' + '{vm_id}'.format(user=owner.email, vm_id=vm.id) + ) + logger.error(error_msg) + admin_email_body['stripe_error_msg'] = error_msg + except HostingOrder.DoesNotExist: + error_msg = ( + "HostingOrder corresponding to vm_id={vm_id} does" + "not exist. Hence, can not find subscription to " + "cancel ".format(vm_id=vm.id) + ) + logger.error(error_msg) + admin_email_body['stripe_error_msg'] = error_msg + terminated = manager.delete_vm(vm.id) if not terminated: - response['text'] = ugettext( - 'Error terminating VM') + opennebula_vm_id + logger.debug( + "manager.delete_vm returned False. Hence, error making " + "xml-rpc call to delete vm failed." + ) + response['text'] = ugettext('Error terminating VM') + vm.id else: for t in range(15): try: - manager.get_vm(opennebula_vm_id) + manager.get_vm(vm.id) except WrongIdError: response['status'] = True response['text'] = ugettext('Terminated') vm_detail_obj = VMDetail.objects.filter( - vm_id=opennebula_vm_id).first() + vm_id=vm.id + ).first() vm_detail_obj.terminated_at = datetime.utcnow() vm_detail_obj.save() - break - except BaseException: + except BaseException as base_exception: + logger.error( + "manager.get_vm({vm_id}) returned exception: " + "{details}.".format( + details=str(base_exception), vm_id=vm.id + ) + ) break else: sleep(2) context = { 'vm_name': vm_name, - 'base_url': "{0}://{1}".format(self.request.scheme, - self.request.get_host()), + 'base_url': "{0}://{1}".format( + self.request.scheme, self.request.get_host() + ), 'page_header': _('Virtual Machine %(vm_name)s Cancelled') % { - 'vm_name': vm_name} + 'vm_name': vm_name + } } email_data = { 'subject': context['page_header'], @@ -1131,6 +1171,18 @@ class VirtualMachineView(LoginRequiredMixin, View): } email = BaseEmail(**email_data) email.send() + admin_email_body.update(response) + email_to_admin_data = { + 'subject': "Deleted VM and Subscription for VM {vm_id} and " + "user: {user}".format( + vm_id=vm.id, user=owner.email + ), + 'from_email': settings.DCL_SUPPORT_FROM_ADDRESS, + 'to': ['info@ungleich.ch'], + 'body': "\n".join( + ["%s=%s" % (k, v) for (k, v) in admin_email_body.items()]), + } + send_plain_email_task.delay(email_to_admin_data) return HttpResponse( json.dumps(response), content_type="application/json" diff --git a/utils/stripe_utils.py b/utils/stripe_utils.py index 8fcf0ab1..58840be0 100644 --- a/utils/stripe_utils.py +++ b/utils/stripe_utils.py @@ -232,6 +232,17 @@ class StripeUtils(object): ) return subscription_result + @handleStripeError + def unsubscribe_customer(self, subscription_id): + """ + Cancels a given subscription + + :param subscription_id: The Stripe subscription id string + :return: + """ + sub = stripe.Subscription.retrieve(subscription_id) + return sub.delete() + @handleStripeError def make_payment(self, customer, amount, token): charge = self.stripe.Charge.create(