Merge branch 'master' into task/3601/reduce_min_ram_to_1G

This commit is contained in:
PCoder 2017-12-22 23:27:32 +01:00
commit 3a558c86a6
3 changed files with 79 additions and 14 deletions

View file

@ -2,6 +2,8 @@ Next:
* #3911: [dcl] Integrate resend activation link into dcl landing payment page * #3911: [dcl] Integrate resend activation link into dcl landing payment page
* #3972: [hosting] Add ungleich company info to invoice footer * #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 * #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 1.2.13: 2017-12-09
* [cms] Introduce UngleichHeaderBackgroundImageAndTextSliderPlugin that allows to have scrolling images and texts * [cms] Introduce UngleichHeaderBackgroundImageAndTextSliderPlugin that allows to have scrolling images and texts
* [cms] Remove <p> tag for ungleich cms customer item template * [cms] Remove <p> tag for ungleich cms customer item template

View file

@ -41,6 +41,7 @@ from utils.forms import (
from utils.hosting_utils import get_vm_price from utils.hosting_utils import get_vm_price
from utils.mailer import BaseEmail from utils.mailer import BaseEmail
from utils.stripe_utils import StripeUtils from utils.stripe_utils import StripeUtils
from utils.tasks import send_plain_email_task
from utils.views import ( from utils.views import (
PasswordResetViewMixin, PasswordResetConfirmViewMixin, LoginViewMixin, PasswordResetViewMixin, PasswordResetConfirmViewMixin, LoginViewMixin,
ResendActivationLinkViewMixin ResendActivationLinkViewMixin
@ -1034,7 +1035,7 @@ class VirtualMachineView(LoginRequiredMixin, View):
) )
return None return None
except Exception as error: except Exception as error:
print(error) logger.error(str(error))
raise Http404() raise Http404()
def get_success_url(self): def get_success_url(self):
@ -1077,49 +1078,88 @@ class VirtualMachineView(LoginRequiredMixin, View):
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
response = {'status': False} response = {'status': False}
admin_email_body = {}
owner = self.request.user owner = self.request.user
vm = self.get_object() vm = self.get_object()
opennebula_vm_id = self.kwargs.get('pk')
manager = OpenNebulaManager( manager = OpenNebulaManager(
email=owner.email, email=owner.email,
password=owner.password password=owner.password
) )
try: try:
vm_data = VirtualMachineSerializer(manager.get_vm(vm.id)).data vm_data = VirtualMachineSerializer(manager.get_vm(vm.id)).data
vm_name = vm_data.get('name') 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')) 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) terminated = manager.delete_vm(vm.id)
if not terminated: if not terminated:
response['text'] = ugettext( logger.debug(
'Error terminating VM') + opennebula_vm_id "manager.delete_vm returned False. Hence, error making "
"xml-rpc call to delete vm failed."
)
response['text'] = ugettext('Error terminating VM') + vm.id
else: else:
for t in range(15): for t in range(15):
try: try:
manager.get_vm(opennebula_vm_id) manager.get_vm(vm.id)
except WrongIdError: except WrongIdError:
response['status'] = True response['status'] = True
response['text'] = ugettext('Terminated') response['text'] = ugettext('Terminated')
vm_detail_obj = VMDetail.objects.filter( 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.terminated_at = datetime.utcnow()
vm_detail_obj.save() vm_detail_obj.save()
break except BaseException as base_exception:
except BaseException: logger.error(
"manager.get_vm({vm_id}) returned exception: "
"{details}.".format(
details=str(base_exception), vm_id=vm.id
)
)
break break
else: else:
sleep(2) sleep(2)
context = { context = {
'vm_name': vm_name, 'vm_name': vm_name,
'base_url': "{0}://{1}".format(self.request.scheme, 'base_url': "{0}://{1}".format(
self.request.get_host()), self.request.scheme, self.request.get_host()
),
'page_header': _('Virtual Machine %(vm_name)s Cancelled') % { 'page_header': _('Virtual Machine %(vm_name)s Cancelled') % {
'vm_name': vm_name} 'vm_name': vm_name
}
} }
email_data = { email_data = {
'subject': context['page_header'], 'subject': context['page_header'],
@ -1131,6 +1171,18 @@ class VirtualMachineView(LoginRequiredMixin, View):
} }
email = BaseEmail(**email_data) email = BaseEmail(**email_data)
email.send() 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( return HttpResponse(
json.dumps(response), json.dumps(response),
content_type="application/json" content_type="application/json"

View file

@ -232,6 +232,17 @@ class StripeUtils(object):
) )
return subscription_result 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 @handleStripeError
def make_payment(self, customer, amount, token): def make_payment(self, customer, amount, token):
charge = self.stripe.Charge.create( charge = self.stripe.Charge.create(