From d8592fc6d8d3e1c3efba54dfe478a1f0d582b917 Mon Sep 17 00:00:00 2001
From: PCoder <purple.coder@yahoo.co.uk>
Date: Sun, 6 Aug 2017 12:30:56 +0530
Subject: [PATCH 01/32] Added celery files

---
 dynamicweb/__init__.py      |  5 +++++
 dynamicweb/celery.py        | 22 ++++++++++++++++++++++
 dynamicweb/settings/base.py |  9 +++++++++
 requirements.txt            |  2 ++
 4 files changed, 38 insertions(+)
 create mode 100644 dynamicweb/celery.py

diff --git a/dynamicweb/__init__.py b/dynamicweb/__init__.py
index e69de29b..b64e43e8 100644
--- a/dynamicweb/__init__.py
+++ b/dynamicweb/__init__.py
@@ -0,0 +1,5 @@
+from __future__ import absolute_import
+
+# This will make sure the app is always imported when
+# Django starts so that shared_task will use this app.
+from .celery import app as celery_app
diff --git a/dynamicweb/celery.py b/dynamicweb/celery.py
new file mode 100644
index 00000000..749ffdef
--- /dev/null
+++ b/dynamicweb/celery.py
@@ -0,0 +1,22 @@
+from __future__ import absolute_import, unicode_literals
+import os
+from celery import Celery
+
+# set the default Django settings module for the 'celery' program.
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dynamicweb.settings')
+
+app = Celery('dynamicweb')
+
+# Using a string here means the worker don't have to serialize
+# the configuration object to child processes.
+# - namespace='CELERY' means all celery-related configuration keys
+#   should have a `CELERY_` prefix.
+app.config_from_object('django.conf:settings', namespace='CELERY')
+
+# Load task modules from all registered Django app configs.
+app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
+
+
+@app.task(bind=True)
+def debug_task(self):
+    print('Request: {0!r}'.format(self.request))
diff --git a/dynamicweb/settings/base.py b/dynamicweb/settings/base.py
index 40187f84..f4c4b68d 100644
--- a/dynamicweb/settings/base.py
+++ b/dynamicweb/settings/base.py
@@ -521,6 +521,15 @@ GOOGLE_ANALYTICS_PROPERTY_IDS = {
     'dynamicweb-staging.ungleich.ch': 'staging'
 }
 
+# CELERY Settings
+#BROKER_URL = 'redis://localhost:6379'
+BROKER_URL = 'redis+socket:///var/run/redis/redis.sock'
+CELERY_RESULT_BACKEND = 'redis://localhost:6379'
+CELERY_ACCEPT_CONTENT = ['application/json']
+CELERY_TASK_SERIALIZER = 'json'
+CELERY_RESULT_SERIALIZER = 'json'
+CELERY_TIMEZONE = 'Europe/Zurich'
+
 ENABLE_DEBUG_LOGGING = bool_env('ENABLE_DEBUG_LOGGING')
 
 if ENABLE_DEBUG_LOGGING:
diff --git a/requirements.txt b/requirements.txt
index f392f4d9..2520d617 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -86,3 +86,5 @@ git+https://github.com/ungleich/python-oca.git#egg=python-oca
 djangorestframework
 flake8==3.3.0
 python-memcached==1.58
+celery==4.0.2
+redis==2.10.5

From 3ad5928aa0930d7a6a41b0791f179cf847cf7a31 Mon Sep 17 00:00:00 2001
From: "M.Ravi" <mondi.ravi@gmail.com>
Date: Sun, 6 Aug 2017 14:33:55 +0200
Subject: [PATCH 02/32] A working version of celery create_vm_task added

---
 datacenterlight/views.py | 121 +++++++--------------------------------
 1 file changed, 22 insertions(+), 99 deletions(-)

diff --git a/datacenterlight/views.py b/datacenterlight/views.py
index f7a07c7e..b2798844 100644
--- a/datacenterlight/views.py
+++ b/datacenterlight/views.py
@@ -4,7 +4,6 @@ from .forms import BetaAccessForm
 from .models import BetaAccess, BetaAccessVMType, BetaAccessVM, VMTemplate
 from django.contrib import messages
 from django.core.urlresolvers import reverse
-from django.core.mail import EmailMessage
 from utils.mailer import BaseEmail
 from django.shortcuts import render
 from django.shortcuts import redirect
@@ -13,14 +12,15 @@ from django.core.exceptions import ValidationError
 from django.views.decorators.cache import cache_control
 from django.conf import settings
 from django.utils.translation import ugettext_lazy as _
-from utils.forms import BillingAddressForm, UserBillingAddressForm
+from utils.forms import BillingAddressForm
 from utils.models import BillingAddress
-from hosting.models import HostingOrder, HostingBill
+from hosting.models import HostingOrder
 from utils.stripe_utils import StripeUtils
-from datetime import datetime
 from membership.models import CustomUser, StripeCustomer
+
 from opennebula_api.models import OpenNebulaManager
 from opennebula_api.serializers import VirtualMachineTemplateSerializer, VirtualMachineSerializer, VMTemplateSerializer
+from datacenterlight.tasks import create_vm_task
 
 
 class LandingProgramView(TemplateView):
@@ -33,7 +33,6 @@ class SuccessView(TemplateView):
     def get(self, request, *args, **kwargs):
         if 'specs' not in request.session or 'user' not in request.session:
             return HttpResponseRedirect(reverse('datacenterlight:index'))
-
         elif 'token' not in request.session:
             return HttpResponseRedirect(reverse('datacenterlight:payment'))
         elif 'order_confirmation' not in request.session:
@@ -79,8 +78,7 @@ class PricingView(TemplateView):
         manager = OpenNebulaManager()
         template = manager.get_template(template_id)
 
-        request.session['template'] = VirtualMachineTemplateSerializer(
-            template).data
+        request.session['template'] = VirtualMachineTemplateSerializer(template).data
 
         if not request.user.is_authenticated():
             request.session['next'] = reverse('hosting:payment')
@@ -132,8 +130,7 @@ class BetaAccessView(FormView):
         email = BaseEmail(**email_data)
         email.send()
 
-        messages.add_message(
-            self.request, messages.SUCCESS, self.success_message)
+        messages.add_message(self.request, messages.SUCCESS, self.success_message)
         return render(self.request, 'datacenterlight/beta_success.html', {})
 
 
@@ -185,8 +182,7 @@ class BetaProgramView(CreateView):
         email = BaseEmail(**email_data)
         email.send()
 
-        messages.add_message(
-            self.request, messages.SUCCESS, self.success_message)
+        messages.add_message(self.request, messages.SUCCESS, self.success_message)
         return HttpResponseRedirect(self.get_success_url())
 
 
@@ -199,15 +195,15 @@ class IndexView(CreateView):
 
     def validate_cores(self, value):
         if (value > 48) or (value < 1):
-            raise ValidationError(_('Invalid number of cores'))
+            raise ValidationError(_('Not a proper cores number'))
 
     def validate_memory(self, value):
         if (value > 200) or (value < 2):
-            raise ValidationError(_('Invalid RAM size'))
+            raise ValidationError(_('Not a proper ram number'))
 
     def validate_storage(self, value):
         if (value > 2000) or (value < 10):
-            raise ValidationError(_('Invalid storage size'))
+            raise ValidationError(_('Not a proper storage number'))
 
     @cache_control(no_cache=True, must_revalidate=True, no_store=True)
     def get(self, request, *args, **kwargs):
@@ -230,8 +226,7 @@ class IndexView(CreateView):
         storage_field = forms.IntegerField(validators=[self.validate_storage])
         price = request.POST.get('total')
         template_id = int(request.POST.get('config'))
-        template = VMTemplate.objects.filter(
-            opennebula_vm_template_id=template_id).first()
+        template = VMTemplate.objects.filter(opennebula_vm_template_id=template_id).first()
         template_data = VMTemplateSerializer(template).data
 
         name = request.POST.get('name')
@@ -243,40 +238,35 @@ class IndexView(CreateView):
             cores = cores_field.clean(cores)
         except ValidationError as err:
             msg = '{} : {}.'.format(cores, str(err))
-            messages.add_message(
-                self.request, messages.ERROR, msg, extra_tags='cores')
+            messages.add_message(self.request, messages.ERROR, msg, extra_tags='cores')
             return HttpResponseRedirect(reverse('datacenterlight:index') + "#order_form")
 
         try:
             memory = memory_field.clean(memory)
         except ValidationError as err:
             msg = '{} : {}.'.format(memory, str(err))
-            messages.add_message(
-                self.request, messages.ERROR, msg, extra_tags='memory')
+            messages.add_message(self.request, messages.ERROR, msg, extra_tags='memory')
             return HttpResponseRedirect(reverse('datacenterlight:index') + "#order_form")
 
         try:
             storage = storage_field.clean(storage)
         except ValidationError as err:
             msg = '{} : {}.'.format(storage, str(err))
-            messages.add_message(
-                self.request, messages.ERROR, msg, extra_tags='storage')
+            messages.add_message(self.request, messages.ERROR, msg, extra_tags='storage')
             return HttpResponseRedirect(reverse('datacenterlight:index') + "#order_form")
 
         try:
             name = name_field.clean(name)
         except ValidationError as err:
             msg = '{} {}.'.format(name, _('is not a proper name'))
-            messages.add_message(
-                self.request, messages.ERROR, msg, extra_tags='name')
+            messages.add_message(self.request, messages.ERROR, msg, extra_tags='name')
             return HttpResponseRedirect(reverse('datacenterlight:index') + "#order_form")
 
         try:
             email = email_field.clean(email)
         except ValidationError as err:
             msg = '{} {}.'.format(email, _('is not a proper email'))
-            messages.add_message(
-                self.request, messages.ERROR, msg, extra_tags='email')
+            messages.add_message(self.request, messages.ERROR, msg, extra_tags='email')
             return HttpResponseRedirect(reverse('datacenterlight:index') + "#order_form")
 
         specs = {
@@ -341,8 +331,7 @@ class IndexView(CreateView):
         email = BaseEmail(**email_data)
         email.send()
 
-        messages.add_message(
-            self.request, messages.SUCCESS, self.success_message)
+        messages.add_message(self.request, messages.SUCCESS, self.success_message)
         return super(IndexView, self).form_valid(form)
 
 
@@ -411,7 +400,6 @@ class PaymentOrderView(FormView):
 
             # Create Billing Address
             billing_address = form.save()
-
             request.session['billing_address_data'] = billing_address_data
             request.session['billing_address'] = billing_address.id
             request.session['token'] = token
@@ -436,8 +424,7 @@ class OrderConfirmationView(DetailView):
         stripe_customer_id = request.session.get('customer')
         customer = StripeCustomer.objects.filter(id=stripe_customer_id).first()
         stripe_utils = StripeUtils()
-        card_details = stripe_utils.get_card_details(
-            customer.stripe_id, request.session.get('token'))
+        card_details = stripe_utils.get_card_details(customer.stripe_id, request.session.get('token'))
         context = {
             'site_url': reverse('datacenterlight:index'),
             'cc_last4': card_details.get('response_object').get('last4'),
@@ -453,8 +440,7 @@ class OrderConfirmationView(DetailView):
         customer = StripeCustomer.objects.filter(id=stripe_customer_id).first()
         billing_address_data = request.session.get('billing_address_data')
         billing_address_id = request.session.get('billing_address')
-        billing_address = BillingAddress.objects.filter(
-            id=billing_address_id).first()
+        billing_address = BillingAddress.objects.filter(id=billing_address_id).first()
         vm_template_id = template.get('id', 1)
         final_price = specs.get('price')
 
@@ -473,71 +459,8 @@ class OrderConfirmationView(DetailView):
             return render(request, self.payment_template_name, context)
 
         charge = charge_response.get('response_object')
-
-        # Create OpenNebulaManager
-        manager = OpenNebulaManager(email=settings.OPENNEBULA_USERNAME,
-                                    password=settings.OPENNEBULA_PASSWORD)
-
-        # Create a vm using oneadmin, also specify the name
-        vm_id = manager.create_vm(
-            template_id=vm_template_id,
-            specs=specs,
-            vm_name="{email}-{template_name}-{date}".format(
-                email=user.get('email'),
-                template_name=template.get('name'),
-                date=int(datetime.now().strftime("%s")))
-        )
-
-        # Create a Hosting Order
-        order = HostingOrder.create(
-            price=final_price,
-            vm_id=vm_id,
-            customer=customer,
-            billing_address=billing_address
-        )
-
-        # Create a Hosting Bill
-        HostingBill.create(
-            customer=customer, billing_address=billing_address)
-
-        # Create Billing Address for User if he does not have one
-        if not customer.user.billing_addresses.count():
-            billing_address_data.update({
-                'user': customer.user.id
-            })
-            billing_address_user_form = UserBillingAddressForm(
-                billing_address_data)
-            billing_address_user_form.is_valid()
-            billing_address_user_form.save()
-
-        # Associate an order with a stripe payment
-        order.set_stripe_charge(charge)
-
-        # If the Stripe payment was successed, set order status approved
-        order.set_approved()
-
-        vm = VirtualMachineSerializer(manager.get_vm(vm_id)).data
-
-        context = {
-            'name': user.get('name'),
-            'email': user.get('email'),
-            'cores': specs.get('cpu'),
-            'memory': specs.get('memory'),
-            'storage': specs.get('disk_size'),
-            'price': specs.get('price'),
-            'template': template.get('name'),
-            'vm.name': vm['name'],
-            'vm.id': vm['vm_id'],
-            'order.id': order.id
-        }
-        email_data = {
-            'subject': settings.DCL_TEXT + " Order from %s" % context['email'],
-            'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
-            'to': ['info@ungleich.ch'],
-            'body': "\n".join(["%s=%s" % (k, v) for (k, v) in context.items()]),
-            'reply_to': [context['email']],
-        }
-        email = EmailMessage(**email_data)
-        email.send()
+        create_vm_task.delay(vm_template_id, user, specs, template, stripe_customer_id, billing_address_data,
+                             billing_address_id,
+                             charge)
         request.session['order_confirmation'] = True
         return HttpResponseRedirect(reverse('datacenterlight:order_success'))

From bd2edf599ae4b8e02cc43167821d9bf3adac75e3 Mon Sep 17 00:00:00 2001
From: "M.Ravi" <mondi.ravi@gmail.com>
Date: Sun, 6 Aug 2017 15:08:05 +0200
Subject: [PATCH 03/32] Merged views from master

---
 datacenterlight/views.py | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/datacenterlight/views.py b/datacenterlight/views.py
index b2798844..e37b2914 100644
--- a/datacenterlight/views.py
+++ b/datacenterlight/views.py
@@ -17,7 +17,6 @@ from utils.models import BillingAddress
 from hosting.models import HostingOrder
 from utils.stripe_utils import StripeUtils
 from membership.models import CustomUser, StripeCustomer
-
 from opennebula_api.models import OpenNebulaManager
 from opennebula_api.serializers import VirtualMachineTemplateSerializer, VirtualMachineSerializer, VMTemplateSerializer
 from datacenterlight.tasks import create_vm_task
@@ -195,15 +194,15 @@ class IndexView(CreateView):
 
     def validate_cores(self, value):
         if (value > 48) or (value < 1):
-            raise ValidationError(_('Not a proper cores number'))
+            raise ValidationError(_('Invalid number of cores'))
 
     def validate_memory(self, value):
         if (value > 200) or (value < 2):
-            raise ValidationError(_('Not a proper ram number'))
+            raise ValidationError(_('Invalid RAM size'))
 
     def validate_storage(self, value):
         if (value > 2000) or (value < 10):
-            raise ValidationError(_('Not a proper storage number'))
+            raise ValidationError(_('Invalid storage size'))
 
     @cache_control(no_cache=True, must_revalidate=True, no_store=True)
     def get(self, request, *args, **kwargs):

From d6d0b9c8c0eed4394d3610ccade37cbc9395fefc Mon Sep 17 00:00:00 2001
From: "M.Ravi" <mondi.ravi@gmail.com>
Date: Sun, 6 Aug 2017 15:08:46 +0200
Subject: [PATCH 04/32] Added default init code for celery

---
 dynamicweb/__init__.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/dynamicweb/__init__.py b/dynamicweb/__init__.py
index b64e43e8..de98902b 100644
--- a/dynamicweb/__init__.py
+++ b/dynamicweb/__init__.py
@@ -1,5 +1,7 @@
-from __future__ import absolute_import
+from __future__ import absolute_import, unicode_literals
 
 # This will make sure the app is always imported when
 # Django starts so that shared_task will use this app.
 from .celery import app as celery_app
+
+__all__ = ['celery_app']
\ No newline at end of file

From 477c8e81a40aeef502764082c5c22b02c77e512a Mon Sep 17 00:00:00 2001
From: "M.Ravi" <mondi.ravi@gmail.com>
Date: Sun, 6 Aug 2017 15:10:26 +0200
Subject: [PATCH 05/32] Added default celery.py code

---
 dynamicweb/celery.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dynamicweb/celery.py b/dynamicweb/celery.py
index 749ffdef..28f6af3b 100644
--- a/dynamicweb/celery.py
+++ b/dynamicweb/celery.py
@@ -14,7 +14,7 @@ app = Celery('dynamicweb')
 app.config_from_object('django.conf:settings', namespace='CELERY')
 
 # Load task modules from all registered Django app configs.
-app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
+app.autodiscover_tasks()
 
 
 @app.task(bind=True)

From 68505e73a8c834f3728e633c38dbf89e7b70de96 Mon Sep 17 00:00:00 2001
From: "M.Ravi" <mondi.ravi@gmail.com>
Date: Sun, 6 Aug 2017 16:32:27 +0200
Subject: [PATCH 06/32] Added django-celery-results and setup redis as backend
 for celery tasks

---
 dynamicweb/settings/base.py | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/dynamicweb/settings/base.py b/dynamicweb/settings/base.py
index f4c4b68d..4847851f 100644
--- a/dynamicweb/settings/base.py
+++ b/dynamicweb/settings/base.py
@@ -120,7 +120,8 @@ INSTALLED_APPS = (
     'datacenterlight.templatetags',
     'alplora',
     'rest_framework',
-    'opennebula_api'
+    'opennebula_api',
+    'django_celery_results',
 )
 
 MIDDLEWARE_CLASSES = (
@@ -522,9 +523,10 @@ GOOGLE_ANALYTICS_PROPERTY_IDS = {
 }
 
 # CELERY Settings
-#BROKER_URL = 'redis://localhost:6379'
-BROKER_URL = 'redis+socket:///var/run/redis/redis.sock'
-CELERY_RESULT_BACKEND = 'redis://localhost:6379'
+# BROKER_URL = 'redis://localhost:6379'
+CELERY_BROKER_URL = 'redis+socket:///tmp/redis.sock'
+# CELERY_RESULT_BACKEND = 'redis://localhost:6379'
+CELERY_RESULT_BACKEND = 'redis+socket:///tmp/redis.sock'
 CELERY_ACCEPT_CONTENT = ['application/json']
 CELERY_TASK_SERIALIZER = 'json'
 CELERY_RESULT_SERIALIZER = 'json'

From 55177646b456be63805604eb5d2188d0c9bd5d4f Mon Sep 17 00:00:00 2001
From: "M.Ravi" <mondi.ravi@gmail.com>
Date: Sun, 6 Aug 2017 16:33:37 +0200
Subject: [PATCH 07/32] Reformatted code

---
 hosting/models.py | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/hosting/models.py b/hosting/models.py
index 88386913..8cdc6114 100644
--- a/hosting/models.py
+++ b/hosting/models.py
@@ -1,13 +1,9 @@
 import os
 import logging
 
-
 from django.db import models
 from django.utils.functional import cached_property
-
-
 from Crypto.PublicKey import RSA
-
 from membership.models import StripeCustomer, CustomUser
 from utils.models import BillingAddress
 from utils.mixins import AssignPermissionsMixin
@@ -42,7 +38,6 @@ class HostingPlan(models.Model):
 
 
 class HostingOrder(AssignPermissionsMixin, models.Model):
-
     ORDER_APPROVED_STATUS = 'Approved'
     ORDER_DECLINED_STATUS = 'Declined'
 
@@ -101,7 +96,7 @@ class HostingOrder(AssignPermissionsMixin, models.Model):
 class UserHostingKey(models.Model):
     user = models.ForeignKey(CustomUser)
     public_key = models.TextField()
-    private_key = models.FileField(upload_to='private_keys',  blank=True)
+    private_key = models.FileField(upload_to='private_keys', blank=True)
     created_at = models.DateTimeField(auto_now_add=True)
     name = models.CharField(max_length=100)
 

From 6d28783f9ffd526aa076289379ffdca927c693b1 Mon Sep 17 00:00:00 2001
From: "M.Ravi" <mondi.ravi@gmail.com>
Date: Sun, 6 Aug 2017 16:34:23 +0200
Subject: [PATCH 08/32] Added django-celery-results to requirements

---
 requirements.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/requirements.txt b/requirements.txt
index 2520d617..abce2271 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -88,3 +88,4 @@ flake8==3.3.0
 python-memcached==1.58
 celery==4.0.2
 redis==2.10.5
+django-celery-results==1.0.1

From 5a5654be018239ae192864316ceb5a4e4c54be99 Mon Sep 17 00:00:00 2001
From: "M.Ravi" <mondi.ravi@gmail.com>
Date: Sun, 6 Aug 2017 16:51:07 +0200
Subject: [PATCH 09/32] Moved CELERY_BROKER_URL and CELERY_RESULT_BACKEND to
 .env file

---
 dynamicweb/settings/base.py | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/dynamicweb/settings/base.py b/dynamicweb/settings/base.py
index 4847851f..fbe0c9ca 100644
--- a/dynamicweb/settings/base.py
+++ b/dynamicweb/settings/base.py
@@ -523,10 +523,8 @@ GOOGLE_ANALYTICS_PROPERTY_IDS = {
 }
 
 # CELERY Settings
-# BROKER_URL = 'redis://localhost:6379'
-CELERY_BROKER_URL = 'redis+socket:///tmp/redis.sock'
-# CELERY_RESULT_BACKEND = 'redis://localhost:6379'
-CELERY_RESULT_BACKEND = 'redis+socket:///tmp/redis.sock'
+CELERY_BROKER_URL = env('CELERY_BROKER_URL')
+CELERY_RESULT_BACKEND = env('CELERY_RESULT_BACKEND')
 CELERY_ACCEPT_CONTENT = ['application/json']
 CELERY_TASK_SERIALIZER = 'json'
 CELERY_RESULT_SERIALIZER = 'json'

From 26b4feb1d16296036ccb3fe75f11f96501f3e964 Mon Sep 17 00:00:00 2001
From: "M.Ravi" <mondi.ravi@gmail.com>
Date: Sun, 6 Aug 2017 18:39:45 +0200
Subject: [PATCH 10/32] Introduced int_env and CELERY_MAX_RETRIES env variable

---
 dynamicweb/settings/base.py | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/dynamicweb/settings/base.py b/dynamicweb/settings/base.py
index fbe0c9ca..58609234 100644
--- a/dynamicweb/settings/base.py
+++ b/dynamicweb/settings/base.py
@@ -10,6 +10,9 @@ from django.utils.translation import ugettext_lazy as _
 
 # dotenv
 import dotenv
+import logging
+
+logger = logging.getLogger(__name__)
 
 
 def gettext(s):
@@ -25,6 +28,20 @@ def bool_env(val):
     return True if os.environ.get(val, False) == 'True' else False
 
 
+def int_env(val, default_value=0):
+    """Replaces string based environment values with Python integers
+    Return default_value if val is not set or cannot be parsed, otherwise
+    returns the python integer equal to the passed val
+    """
+    return_value = default_value
+    try:
+        return_value = int(os.environ.get(val))
+    except Exception as e:
+        logger.error(str(e))
+
+    return return_value
+
+
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
 PROJECT_DIR = os.path.abspath(
@@ -529,6 +546,7 @@ CELERY_ACCEPT_CONTENT = ['application/json']
 CELERY_TASK_SERIALIZER = 'json'
 CELERY_RESULT_SERIALIZER = 'json'
 CELERY_TIMEZONE = 'Europe/Zurich'
+CELERY_MAX_RETRIES = int_env('CELERY_MAX_RETRIES', 5)
 
 ENABLE_DEBUG_LOGGING = bool_env('ENABLE_DEBUG_LOGGING')
 

From f950c1defb23a0cba62bbbbb732a5428f2f416a5 Mon Sep 17 00:00:00 2001
From: "M.Ravi" <mondi.ravi@gmail.com>
Date: Sun, 6 Aug 2017 18:42:27 +0200
Subject: [PATCH 11/32] Added datacenterlight/tasks.py

---
 datacenterlight/tasks.py | 162 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 162 insertions(+)
 create mode 100644 datacenterlight/tasks.py

diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py
new file mode 100644
index 00000000..69ba08ad
--- /dev/null
+++ b/datacenterlight/tasks.py
@@ -0,0 +1,162 @@
+from __future__ import absolute_import, unicode_literals
+from dynamicweb.celery import app
+from celery.utils.log import get_task_logger
+from django.conf import settings
+from opennebula_api.models import OpenNebulaManager
+from opennebula_api.serializers import VirtualMachineSerializer
+from hosting.models import HostingOrder, HostingBill
+from utils.forms import UserBillingAddressForm
+from datetime import datetime
+from membership.models import StripeCustomer
+from django.core.mail import EmailMessage
+from utils.models import BillingAddress
+
+logger = get_task_logger(__name__)
+
+
+def retry_task(task, exception=None):
+    """Retries the specified task using a "backing off countdown",
+    meaning that the interval between retries grows exponentially
+    with every retry.
+
+    Arguments:
+        task:
+            The task to retry.
+
+        exception:
+            Optionally, the exception that caused the retry.
+    """
+
+    def backoff(attempts):
+        return 2 ** attempts
+
+    kwargs = {
+        'countdown': backoff(task.request.retries),
+    }
+
+    if exception:
+        kwargs['exc'] = exception
+
+    if task.request.retries > settings.CELERY_MAX_RETRIES:
+        msg_text = 'Finished {} retries for create_vm_task'.format(task.request.retries)
+        logger.log(msg_text)
+        # Try sending email and stop
+        email_data = {
+            'subject': '{} CELERY TASK ERROR: {}'.format(settings.DCL_TEXT, msg_text),
+            'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
+            'to': ['info@ungleich.ch'],
+            'body': "\n".join(["%s=%s" % (k, v) for (k, v) in kwargs.items()]),
+        }
+        email = EmailMessage(**email_data)
+        email.send()
+        return
+    else:
+        raise task.retry(**kwargs)
+
+
+@app.task(bind=True)
+def create_vm_task(self, vm_template_id, user, specs, template, stripe_customer_id, billing_address_data,
+                   billing_address_id,
+                   charge):
+    try:
+        final_price = specs.get('price')
+        billing_address = BillingAddress.objects.filter(id=billing_address_id).first()
+        customer = StripeCustomer.objects.filter(id=stripe_customer_id).first()
+        # Create OpenNebulaManager
+        manager = OpenNebulaManager(email=settings.OPENNEBULA_USERNAME,
+                                    password=settings.OPENNEBULA_PASSWORD)
+
+        # Create a vm using oneadmin, also specify the name
+        vm_id = manager.create_vm(
+            template_id=vm_template_id,
+            specs=specs,
+            vm_name="{email}-{template_name}-{date}".format(
+                email=user.get('email'),
+                template_name=template.get('name'),
+                date=int(datetime.now().strftime("%s")))
+        )
+
+        # Create a Hosting Order
+        order = HostingOrder.create(
+            price=final_price,
+            vm_id=vm_id,
+            customer=customer,
+            billing_address=billing_address
+        )
+
+        # Create a Hosting Bill
+        HostingBill.create(
+            customer=customer, billing_address=billing_address)
+
+        # Create Billing Address for User if he does not have one
+        if not customer.user.billing_addresses.count():
+            billing_address_data.update({
+                'user': customer.user.id
+            })
+            billing_address_user_form = UserBillingAddressForm(
+                billing_address_data)
+            billing_address_user_form.is_valid()
+            billing_address_user_form.save()
+
+        # Associate an order with a stripe payment
+        charge_object = DictDotLookup(charge)
+        order.set_stripe_charge(charge_object)
+
+        # If the Stripe payment succeeds, set order status approved
+        order.set_approved()
+
+        vm = VirtualMachineSerializer(manager.get_vm(vm_id)).data
+
+        context = {
+            'name': user.get('name'),
+            'email': user.get('email'),
+            'cores': specs.get('cpu'),
+            'memory': specs.get('memory'),
+            'storage': specs.get('disk_size'),
+            'price': specs.get('price'),
+            'template': template.get('name'),
+            'vm.name': vm['name'],
+            'vm.id': vm['vm_id'],
+            'order.id': order.id
+        }
+        email_data = {
+            'subject': settings.DCL_TEXT + " Order from %s" % context['email'],
+            'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
+            'to': ['info@ungleich.ch'],
+            'body': "\n".join(["%s=%s" % (k, v) for (k, v) in context.items()]),
+            'reply_to': [context['email']],
+        }
+        email = EmailMessage(**email_data)
+        email.send()
+    except Exception as e:
+        logger.error(str(e))
+        retry_task(self)
+
+
+class DictDotLookup(object):
+    """
+    Creates objects that behave much like a dictionaries, but allow nested
+    key access using object '.' (dot) lookups.
+    """
+
+    def __init__(self, d):
+        for k in d:
+            if isinstance(d[k], dict):
+                self.__dict__[k] = DictDotLookup(d[k])
+            elif isinstance(d[k], (list, tuple)):
+                l = []
+                for v in d[k]:
+                    if isinstance(v, dict):
+                        l.append(DictDotLookup(v))
+                    else:
+                        l.append(v)
+                self.__dict__[k] = l
+            else:
+                self.__dict__[k] = d[k]
+
+    def __getitem__(self, name):
+        if name in self.__dict__:
+            return self.__dict__[name]
+
+    def __iter__(self):
+        return iter(self.__dict__.keys())

From e7864f5d85788a44abab26ded38e5ec1808fc7a8 Mon Sep 17 00:00:00 2001
From: "M.Ravi" <mondi.ravi@gmail.com>
Date: Sun, 6 Aug 2017 18:52:23 +0200
Subject: [PATCH 12/32] Added condition to check if create_vm succeeded

---
 datacenterlight/tasks.py | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py
index 69ba08ad..9f0249a2 100644
--- a/datacenterlight/tasks.py
+++ b/datacenterlight/tasks.py
@@ -58,6 +58,7 @@ def retry_task(task, exception=None):
 def create_vm_task(self, vm_template_id, user, specs, template, stripe_customer_id, billing_address_data,
                    billing_address_id,
                    charge):
+    vm_id = None
     try:
         final_price = specs.get('price')
         billing_address = BillingAddress.objects.filter(id=billing_address_id).first()
@@ -76,6 +77,9 @@ def create_vm_task(self, vm_template_id, user, specs, template, stripe_customer_
                 date=int(datetime.now().strftime("%s")))
         )
 
+        if vm_id is None:
+            raise Exception("Could not create VM")
+
         # Create a Hosting Order
         order = HostingOrder.create(
             price=final_price,
@@ -132,6 +136,8 @@ def create_vm_task(self, vm_template_id, user, specs, template, stripe_customer_
         logger.error(str(e))
         retry_task(self)
 
+    return vm_id
+
 
 class DictDotLookup(object):
     """

From 58bb75481491589d9024c399e448f3ae8336683d Mon Sep 17 00:00:00 2001
From: "M.Ravi" <mondi.ravi@gmail.com>
Date: Sun, 6 Aug 2017 21:54:12 +0200
Subject: [PATCH 13/32] Introduced MaxRetries and MaxRetriesExceededError
 handling code

---
 datacenterlight/tasks.py | 35 ++++++++++++++++++-----------------
 1 file changed, 18 insertions(+), 17 deletions(-)

diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py
index 9f0249a2..342c87f4 100644
--- a/datacenterlight/tasks.py
+++ b/datacenterlight/tasks.py
@@ -10,6 +10,7 @@ from datetime import datetime
 from membership.models import StripeCustomer
 from django.core.mail import EmailMessage
 from utils.models import BillingAddress
+from celery.exceptions import MaxRetriesExceededError
 
 logger = get_task_logger(__name__)
 
@@ -37,24 +38,10 @@ def retry_task(task, exception=None):
     if exception:
         kwargs['exc'] = exception
 
-    if task.request.retries > settings.CELERY_MAX_RETRIES:
-        msg_text = 'Finished {} retries for create_vm_task'.format(task.request.retries)
-        logger.log(msg_text)
-        # Try sending email and stop
-        email_data = {
-            'subject': '{} CELERY TASK ERROR: {}'.format(settings.DCL_TEXT, msg_text),
-            'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
-            'to': ['info@ungleich.ch'],
-            'body': "\n".join(["%s=%s" % (k, v) for (k, v) in kwargs.items()]),
-        }
-        email = EmailMessage(**email_data)
-        email.send()
-        return
-    else:
-        raise task.retry(**kwargs)
+    raise task.retry(**kwargs)
 
 
-@app.task(bind=True)
+@app.task(bind=True, max_retries=settings.CELERY_MAX_RETRIES)
 def create_vm_task(self, vm_template_id, user, specs, template, stripe_customer_id, billing_address_data,
                    billing_address_id,
                    charge):
@@ -134,7 +121,21 @@ def create_vm_task(self, vm_template_id, user, specs, template, stripe_customer_
         email.send()
     except Exception as e:
         logger.error(str(e))
-        retry_task(self)
+        try:
+            retry_task(self)
+        except MaxRetriesExceededError:
+            msg_text = 'Finished {} retries for create_vm_task'.format(self.request.retries)
+            logger.error(msg_text)
+            # Try sending email and stop
+            email_data = {
+                'subject': '{} CELERY TASK ERROR: {}'.format(settings.DCL_TEXT, msg_text),
+                'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
+                'to': ['info@ungleich.ch'],
+                'body':',\n'.join(str(i) for i in self.request.args)
+            }
+            email = EmailMessage(**email_data)
+            email.send()
+            return
 
     return vm_id
 

From 29b28d551c2f3caf20929f6eb5f57187ed81c9f9 Mon Sep 17 00:00:00 2001
From: "M.Ravi" <mondi.ravi@gmail.com>
Date: Sun, 6 Aug 2017 22:19:27 +0200
Subject: [PATCH 14/32] Fixed flake8 lint warnings

---
 datacenterlight/tasks.py | 2 +-
 datacenterlight/views.py | 4 +---
 dynamicweb/__init__.py   | 2 +-
 3 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py
index 342c87f4..dc71fcee 100644
--- a/datacenterlight/tasks.py
+++ b/datacenterlight/tasks.py
@@ -131,7 +131,7 @@ def create_vm_task(self, vm_template_id, user, specs, template, stripe_customer_
                 'subject': '{} CELERY TASK ERROR: {}'.format(settings.DCL_TEXT, msg_text),
                 'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
                 'to': ['info@ungleich.ch'],
-                'body':',\n'.join(str(i) for i in self.request.args)
+                'body': ',\n'.join(str(i) for i in self.request.args)
             }
             email = EmailMessage(**email_data)
             email.send()
diff --git a/datacenterlight/views.py b/datacenterlight/views.py
index e37b2914..2bae5c77 100644
--- a/datacenterlight/views.py
+++ b/datacenterlight/views.py
@@ -13,12 +13,11 @@ from django.views.decorators.cache import cache_control
 from django.conf import settings
 from django.utils.translation import ugettext_lazy as _
 from utils.forms import BillingAddressForm
-from utils.models import BillingAddress
 from hosting.models import HostingOrder
 from utils.stripe_utils import StripeUtils
 from membership.models import CustomUser, StripeCustomer
 from opennebula_api.models import OpenNebulaManager
-from opennebula_api.serializers import VirtualMachineTemplateSerializer, VirtualMachineSerializer, VMTemplateSerializer
+from opennebula_api.serializers import VirtualMachineTemplateSerializer, VMTemplateSerializer
 from datacenterlight.tasks import create_vm_task
 
 
@@ -439,7 +438,6 @@ class OrderConfirmationView(DetailView):
         customer = StripeCustomer.objects.filter(id=stripe_customer_id).first()
         billing_address_data = request.session.get('billing_address_data')
         billing_address_id = request.session.get('billing_address')
-        billing_address = BillingAddress.objects.filter(id=billing_address_id).first()
         vm_template_id = template.get('id', 1)
         final_price = specs.get('price')
 
diff --git a/dynamicweb/__init__.py b/dynamicweb/__init__.py
index de98902b..3b91b070 100644
--- a/dynamicweb/__init__.py
+++ b/dynamicweb/__init__.py
@@ -4,4 +4,4 @@ from __future__ import absolute_import, unicode_literals
 # Django starts so that shared_task will use this app.
 from .celery import app as celery_app
 
-__all__ = ['celery_app']
\ No newline at end of file
+__all__ = ['celery_app']

From 227d3a20a526f3e30915e99a2b0fc3d4ef0fbbe9 Mon Sep 17 00:00:00 2001
From: PCoder <purple.coder@yahoo.co.uk>
Date: Tue, 8 Aug 2017 01:57:29 +0530
Subject: [PATCH 15/32] Removed __future__

---
 dynamicweb/__init__.py | 2 --
 dynamicweb/celery.py   | 1 -
 2 files changed, 3 deletions(-)

diff --git a/dynamicweb/__init__.py b/dynamicweb/__init__.py
index 3b91b070..1a6c551d 100644
--- a/dynamicweb/__init__.py
+++ b/dynamicweb/__init__.py
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, unicode_literals
-
 # This will make sure the app is always imported when
 # Django starts so that shared_task will use this app.
 from .celery import app as celery_app
diff --git a/dynamicweb/celery.py b/dynamicweb/celery.py
index 28f6af3b..609ef5c4 100644
--- a/dynamicweb/celery.py
+++ b/dynamicweb/celery.py
@@ -1,4 +1,3 @@
-from __future__ import absolute_import, unicode_literals
 import os
 from celery import Celery
 

From 8029f058243c02d13f45c277d6c4f552b034c701 Mon Sep 17 00:00:00 2001
From: PCoder <purple.coder@yahoo.co.uk>
Date: Tue, 8 Aug 2017 02:12:13 +0530
Subject: [PATCH 16/32] Added env variable to logger message

---
 dynamicweb/settings/base.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/dynamicweb/settings/base.py b/dynamicweb/settings/base.py
index 58609234..a0d31592 100644
--- a/dynamicweb/settings/base.py
+++ b/dynamicweb/settings/base.py
@@ -37,7 +37,8 @@ def int_env(val, default_value=0):
     try:
         return_value = int(os.environ.get(val))
     except Exception as e:
-        logger.error(str(e))
+        logger.error("Encountered exception trying to get env value for {}\nException details: {}".format(
+            val, str(e)))
 
     return return_value
 

From e92e3a9527d348a6976d02d32732316fb7cb1d1b Mon Sep 17 00:00:00 2001
From: Arvind Tiwari <tiwariav@gmail.com>
Date: Wed, 16 Aug 2017 04:02:22 +0530
Subject: [PATCH 17/32] new design for page /my-virtual-machines

---
 hosting/static/hosting/css/commons.css        |  88 ++++++++---
 .../static/hosting/css/virtual-machine.css    | 143 ++++++++++++++++++
 hosting/static/hosting/img/copy.svg           |   7 +
 hosting/static/hosting/img/vm.svg             |   7 +
 .../templates/hosting/virtual_machines.html   |  72 ++++++++-
 5 files changed, 294 insertions(+), 23 deletions(-)
 create mode 100644 hosting/static/hosting/img/copy.svg
 create mode 100644 hosting/static/hosting/img/vm.svg

diff --git a/hosting/static/hosting/css/commons.css b/hosting/static/hosting/css/commons.css
index 156e1974..1ebae4b4 100644
--- a/hosting/static/hosting/css/commons.css
+++ b/hosting/static/hosting/css/commons.css
@@ -162,29 +162,75 @@
 
 /* ========= */
 @media(min-width: 320px) {
-   .modal:before {
-     content: '';
-     display: inline-block;
-     height: 100%;
-     vertical-align: middle;
-     margin-right: -4px;
-   }
- }
+  .modal:before {
+    content: '';
+    display: inline-block;
+    height: 100%;
+    vertical-align: middle;
+    margin-right: -4px;
+  }
+}
 
 
- @media (min-width: 768px) {
-   .modal-dialog {
+@media (min-width: 768px) {
+  .modal-dialog {
 /*        width: 520px; */
-       margin: 15px auto;
-   }
- }
+      margin: 15px auto;
+  }
+}
 
- .modal {
-   text-align: center;
- }
+.modal {
+  text-align: center;
+}
 
- .modal-dialog {
-   display: inline-block;
-   text-align: left;
-   vertical-align: middle;
- }
+.modal-dialog {
+  display: inline-block;
+  text-align: left;
+  vertical-align: middle;
+}
+
+.un-icon {
+  width: 15px;
+  height: 15px;
+  opacity: 0.5;
+  margin-top: -1px;
+}
+
+.css-plus {
+  position: relative;
+  width: 16px;
+  height: 20px;
+  display: inline-block;
+  vertical-align: middle;
+  /*   top: -1px; */
+}
+
+.css-plus + span {
+  vertical-align: middle;
+}
+
+.css-plus:before {
+  content: '';
+  width: 10px;
+  height: 2px;
+  background: #f6f7f9;
+  position: absolute;
+  left: 50%;
+  top: 50%;
+  -webkit-transform: translate(-50%,-50%);
+  -ms-transform: translate(-50%,-50%);
+  transform: translate(-50%,-50%);
+}
+
+.css-plus:after {
+  content: '';
+  width: 2px;
+  height: 10px;
+  background: #f6f7f9;
+  position: absolute;
+  left: 50%;
+  top: 50%;
+  -webkit-transform: translate(-50%,-50%);
+  -ms-transform: translate(-50%,-50%);
+  transform: translate(-50%,-50%);
+}
\ No newline at end of file
diff --git a/hosting/static/hosting/css/virtual-machine.css b/hosting/static/hosting/css/virtual-machine.css
index e043879d..0dd89866 100644
--- a/hosting/static/hosting/css/virtual-machine.css
+++ b/hosting/static/hosting/css/virtual-machine.css
@@ -227,4 +227,147 @@
     .btn-create-vm {
       float: left !important; 
     }
+}
+
+/* New styles */
+.dashboard-title-thin {
+  font-weight: 300;
+  font-size: 32px;
+}
+
+.dashboard-title-thin .un-icon {
+  height: 34px;
+  margin-right: 5px;
+  margin-top: -1px;
+  width: 20px;
+}
+
+.dashboard-subtitle {
+  font-weight: 300;
+  margin-bottom: 25px;
+}
+
+.btn-vm {
+  background: #1596DA;
+  color: #fff;
+  font-weight: 400;
+  letter-spacing: 0.8px;
+  border-radius: 3px;
+  padding-bottom: 7px;
+  border: 2px solid #1596DA;
+}
+
+.btn-vm:hover, .btn-vm:focus {
+  color: #1596DA;
+  background: #fff;
+}
+.btn-vm:hover .css-plus:after,
+.btn-vm:focus .css-plus:after,
+.btn-vm:hover .css-plus:before,
+.btn-vm:focus .css-plus:before {
+  background: #1596DA;
+}
+.btn-vm-detail {
+  background: #3770CC;
+  color: #fff;
+  font-weight: 400;
+  letter-spacing: 0.6px;
+  font-size: 14px;
+  border-radius: 3px;
+  border: 2px solid #3770CC;
+  padding: 4px 20px;
+  /*   padding-bottom: 7px; */
+}
+
+.btn-vm-detail:hover, .btn-vm-detail:focus {
+  background: #fff;
+  color: #3770CC;
+}
+
+.vm-status, .vm-status-active, .vm-status-failed {
+  font-weight: 600;
+}
+.vm-status-active {
+  color: #4A90E2;
+}
+.vm-status-failed {
+  color: #eb4d5c;
+}
+
+@media (min-width:768px) {
+  .dashboard-subtitle {
+    display: flex;
+    justify-content: space-between;
+    font-size: 16px;
+  }
+}
+@media (max-width:767px) {
+  .dashboard-title-thin {
+    font-size: 22px;
+  }
+  .dashboard-title-thin .un-icon {
+    height: 20px;
+    width: 18px;
+    margin-top: -3px;
+  }
+  .dashboard-subtitle p {
+    width: 200px;
+  }
+}
+
+.table-switch {
+  color: #555;
+}
+
+.table-switch > tbody > tr > td {
+  padding: 12px 8px;
+}
+
+@media (min-width: 768px) {
+  .table-switch > tbody > tr > td:nth-child(1) {
+    padding-right: 45px;
+  }
+}
+
+.table-switch .un-icon {
+  margin-left: 5px;
+}
+
+@media (max-width:767px) {
+  .dashboard-subtitle {
+    margin-bottom: 15px;
+  }
+  .table-switch .un-icon {
+    float: right;
+    margin-top: 0;
+  }
+  .table-switch thead {
+    display: none;
+  }
+  .table-switch tbody tr {
+    display: block;
+    position: relative;
+    border-top: 1px solid #ddd;
+    margin-top: 15px;
+    padding-top: 5px;
+  }
+  .table-switch tbody tr td {
+    display: block;
+    padding-top: 28px;
+    padding-bottom: 6px;
+    position: relative;
+    border: 0;
+  }
+  .table-switch td:before {
+    content: attr(data-header);
+    font-weight: 600;
+    position: absolute;
+    top: 5px;
+
+  }
+  .table-switch .last-td {
+    position: absolute;
+    bottom: 5px;
+    right: 0;
+  }
 }
\ No newline at end of file
diff --git a/hosting/static/hosting/img/copy.svg b/hosting/static/hosting/img/copy.svg
new file mode 100644
index 00000000..c30b5922
--- /dev/null
+++ b/hosting/static/hosting/img/copy.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
+<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
+<g><path d="M691,160.8V10H269.5C206.3,72.6,143.1,135.2,80,197.8v641.4h227.9V990H920V160.8H691z M269.5,64.4v134.4H133.1C178.5,154,224,109.2,269.5,64.4z M307.9,801.2H117.5V236.8h190.5V47.9h344.5v112.9h-154c-63.5,62.9-127,125.9-190.5,188.8V801.2z M499.5,215.2v134.5H363.1v-1c45.1-44.5,90.2-89,135.3-133.5L499.5,215.2z M881.5,952h-535V386.6H538V198.8h343.5V952z"/></g>
+</svg>
\ No newline at end of file
diff --git a/hosting/static/hosting/img/vm.svg b/hosting/static/hosting/img/vm.svg
new file mode 100644
index 00000000..376e7d0a
--- /dev/null
+++ b/hosting/static/hosting/img/vm.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
+<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
+<g><path d="M724.6,224.4c0,28.2,22.9,51,51,51s51-22.9,51-51c0-28.2-22.9-51-51-51S724.6,196.2,724.6,224.4z M724.6,551c0,28.2,22.9,51,51,51s51-22.9,51-51c0-28.2-22.9-51-51-51S724.6,522.9,724.6,551L724.6,551z M10,683.7c0,45.1,36.5,81.7,81.7,81.7h347.1v56.4c-10,6.7-18.6,15.3-25.3,25.3l-250.3,0c-28.2,0-51,22.9-51,51s22.9,51,51,51h250.3c16.5,24.7,44.5,40.8,76.4,40.8c31.8,0,59.8-16.1,76.4-40.8h270.7c28.2,0,51-22.9,51-51s-22.9-51-51-51H566.2c-6.7-10-15.3-18.6-25.3-25.3v-56.3h367.5c45.1,0,81.7-36.5,81.7-81.7V91.7c0-45.1-36.5-81.7-81.7-81.7H91.7C46.5,10,10,46.5,10,91.7L10,683.7L10,683.7z M157,112.1h686c24.9,0,44.9,20,44.9,44.9v134.7c0,24.9-20,44.9-44.9,44.9H157c-24.9,0-44.9-20-44.9-44.9V157C112.1,132.1,132.1,112.1,157,112.1L157,112.1L157,112.1z M157,438.7h686c24.9,0,44.9,20,44.9,44.9v134.7c0,24.9-20,44.9-44.9,44.9H157c-24.9,0-44.9-20-44.9-44.9V483.7C112.1,458.8,132.1,438.7,157,438.7L157,438.7L157,438.7z"/></g>
+</svg>
\ No newline at end of file
diff --git a/hosting/templates/hosting/virtual_machines.html b/hosting/templates/hosting/virtual_machines.html
index c149be41..5ee9e1ff 100644
--- a/hosting/templates/hosting/virtual_machines.html
+++ b/hosting/templates/hosting/virtual_machines.html
@@ -1,6 +1,75 @@
 {% extends "hosting/base_short.html" %}
 {% load staticfiles bootstrap3 i18n %}
 {% block content %}
+<div class="dashboard-container">
+    <h3 class="dashboard-title-thin"><img src="{% static 'hosting/img/vm.svg' %}" class="un-icon"> {% trans "Virtual Machines" %}</h3>
+    <div class="dashboard-subtitle">
+        <p>{% trans 'To create a new virtual machine, click "Create VM"' %}</p>
+        <div class="text-right">
+            <a class="btn btn-vm" href="{% url 'hosting:create_virtual_machine' %}"><span class="css-plus"></span> <span>{% trans "CREATE VM"%}</span></a>
+        </div>
+    </div>
+
+    <table class="table table-switch">
+        <thead>
+            <tr>
+                <th>ID</th>
+                <th>Ipv4</th>
+                <th>Ipv6</th>
+                <th>{% trans "Status" %}</th>
+                <th></th>
+            </tr>
+        </thead>
+        <tbody>
+            {% for vm in vms %}
+            <tr>
+                <td data-header="ID">{{vm.vm_id}}</td>
+                {% if vm.ipv6  %}
+                    <td data-header="Ipv4">{{vm.ipv4}}</td>
+                    <td data-header="Ipv6">{{vm.ipv6}}</td>
+                {% endif %}
+                <td data-header="{% trans 'Status' %}">
+                    {% if vm.state == 'ACTIVE' %}
+                        <span class="vm-status-active"><strong>{{vm.state}}</strong></span>
+                    {% elif  vm.state == 'FAILED' %}
+                        <span class="vm-status-failed"><strong>{{vm.state}}</strong></span>
+                    {% else %}
+                        <span class="vm-status"><strong>{{vm.state}}</strong></span>
+                    {% endif %}
+
+                </td>
+                <td class="text-right last-td">
+                    <a class="btn btn-vm-detail" href="{% url 'hosting:virtual_machines' vm.vm_id %}">{% trans "View Detail"%}</a>
+                </td>
+            </tr>
+            {% endfor %}
+            <tr>
+                <td data-header="ID">13638</td>
+                <td data-header="Ipv4">185.203.112.75 <img src="{% static 'hosting/img/copy.svg' %}" class="un-icon"></td>
+                <td data-header="Ipv6">2a0a:e5c0:0:2:400:b3ff:fe39:7996 <img src="{% static 'hosting/img/copy.svg' %}" class="un-icon"></td>
+                <td data-header="{% trans 'Status' %}">
+                    <span class="vm-status-active">Active</span>
+                </td>
+                <td class="text-right last-td">
+                    <a class="btn btn-vm-detail" href="/hosting/my-virtual-machines/13638">View Detail</a>
+                </td>
+            </tr>
+            <tr>
+                <td data-header="ID">13638</td>
+                <td data-header="Ipv4">185.203.112.75 <img src="{% static 'hosting/img/copy.svg' %}" class="un-icon"></td>
+                <td data-header="Ipv6">2a0a:e5c0:0:2:400:b3ff:fe39:7996 <img src="{% static 'hosting/img/copy.svg' %}" class="un-icon"></td>
+                <td data-header="Status">
+                    <span class="vm-status-failed">Failed</span>
+                </td>
+                <td class="text-right last-td">
+                    <a class="btn btn-vm-detail" href="/hosting/my-virtual-machines/13638">View Detail</a>
+                </td>
+            </tr>
+        </tbody>
+    </table>
+</div>
+
+{% comment %}
 <div>
 	<div class="dashboard-container">
 		<div class="row">
@@ -78,12 +147,11 @@
 			            </span>
 			        </div>
 			    {% endif %}
-
 			</div>
 
 	    </div>
 	</div>
 
 </div>
-
+{% endcomment %}
 {%endblock%}

From aec4073af5115a3a1c7cc7a16ac3b0d3feac312a Mon Sep 17 00:00:00 2001
From: Arvind Tiwari <tiwariav@gmail.com>
Date: Wed, 16 Aug 2017 04:08:44 +0530
Subject: [PATCH 18/32] removed testing markup from html

---
 .../templates/hosting/virtual_machines.html   | 23 -------------------
 1 file changed, 23 deletions(-)

diff --git a/hosting/templates/hosting/virtual_machines.html b/hosting/templates/hosting/virtual_machines.html
index 5ee9e1ff..db1909a4 100644
--- a/hosting/templates/hosting/virtual_machines.html
+++ b/hosting/templates/hosting/virtual_machines.html
@@ -36,35 +36,12 @@
                     {% else %}
                         <span class="vm-status"><strong>{{vm.state}}</strong></span>
                     {% endif %}
-
                 </td>
                 <td class="text-right last-td">
                     <a class="btn btn-vm-detail" href="{% url 'hosting:virtual_machines' vm.vm_id %}">{% trans "View Detail"%}</a>
                 </td>
             </tr>
             {% endfor %}
-            <tr>
-                <td data-header="ID">13638</td>
-                <td data-header="Ipv4">185.203.112.75 <img src="{% static 'hosting/img/copy.svg' %}" class="un-icon"></td>
-                <td data-header="Ipv6">2a0a:e5c0:0:2:400:b3ff:fe39:7996 <img src="{% static 'hosting/img/copy.svg' %}" class="un-icon"></td>
-                <td data-header="{% trans 'Status' %}">
-                    <span class="vm-status-active">Active</span>
-                </td>
-                <td class="text-right last-td">
-                    <a class="btn btn-vm-detail" href="/hosting/my-virtual-machines/13638">View Detail</a>
-                </td>
-            </tr>
-            <tr>
-                <td data-header="ID">13638</td>
-                <td data-header="Ipv4">185.203.112.75 <img src="{% static 'hosting/img/copy.svg' %}" class="un-icon"></td>
-                <td data-header="Ipv6">2a0a:e5c0:0:2:400:b3ff:fe39:7996 <img src="{% static 'hosting/img/copy.svg' %}" class="un-icon"></td>
-                <td data-header="Status">
-                    <span class="vm-status-failed">Failed</span>
-                </td>
-                <td class="text-right last-td">
-                    <a class="btn btn-vm-detail" href="/hosting/my-virtual-machines/13638">View Detail</a>
-                </td>
-            </tr>
         </tbody>
     </table>
 </div>

From 8160e53ea71d8bc152be424002969b7048323cb8 Mon Sep 17 00:00:00 2001
From: Arvind Tiwari <tiwariav@gmail.com>
Date: Wed, 16 Aug 2017 04:10:08 +0530
Subject: [PATCH 19/32] removed commented html

---
 .../templates/hosting/virtual_machines.html   | 87 +------------------
 1 file changed, 1 insertion(+), 86 deletions(-)

diff --git a/hosting/templates/hosting/virtual_machines.html b/hosting/templates/hosting/virtual_machines.html
index db1909a4..2d033a8d 100644
--- a/hosting/templates/hosting/virtual_machines.html
+++ b/hosting/templates/hosting/virtual_machines.html
@@ -1,5 +1,6 @@
 {% extends "hosting/base_short.html" %}
 {% load staticfiles bootstrap3 i18n %}
+
 {% block content %}
 <div class="dashboard-container">
     <h3 class="dashboard-title-thin"><img src="{% static 'hosting/img/vm.svg' %}" class="un-icon"> {% trans "Virtual Machines" %}</h3>
@@ -45,90 +46,4 @@
         </tbody>
     </table>
 </div>
-
-{% comment %}
-<div>
-	<div class="dashboard-container">
-		<div class="row">
-			<div class="col-xs-12  container-table">
-				<table class="table borderless table-hover">
-				<h3 class="pull-left"><i class="fa fa-server fa-separate" aria-hidden="true"></i> {% trans "Virtual Machines"%}</h3>
-                <div class="col-md-12">
-                    <br/>
-                    {% if messages %}
-                        <div class="alert alert-warning">
-                            {% for message in messages %}
-                            <span>{{ message }}</span>
-                            {% endfor %}
-                        </div>
-                    {% endif %}
-                </div>
-                {% if not error %}
-                <p class="pull-right btn-create-vm">
-                    <a class="btn btn-success" href="{% url 'hosting:create_virtual_machine' %}" >{% trans "Create VM"%} </a>
-                </p>
-				<br/>
-
-				<thead>
-				<tr>
-					<th>{% trans "ID"%}</th>
-                    <th>{% trans "Ipv4"%}</th>
-					<th>{% trans "Ipv6"%}</th>
-					<th>{% trans "Status"%}</th>
-					<th></th>
-				</tr>
-				</thead>
-				<tbody>
-					{% for vm in vms %}
-					<tr>
-						<td scope="row">{{vm.vm_id}}</td>
-                        {% if vm.ipv6  %}
-						  <td>{{vm.ipv4}}</td>
-
-                          <td>{{vm.ipv6}}</td>
-                        {% endif %}
-
-						<td>
-
-							{% if vm.state == 'ACTIVE' %}
-								<span class="h3 label label-success"><strong> {{vm.state}}</strong></span>
-							{% elif  vm.state == 'FAILED' %}
-								<span class="h3 label label-danger"><strong>{{vm.state}}</strong></span>
-							{% else %}
-								<span class="h3 label label-warning"><strong>{{vm.state}}</strong></span>
-							{% endif %}
-
-						</td>
-						<td>
-                            <button type="button" class="btn btn-default"><a
-                                    href="{% url 'hosting:virtual_machines' vm.vm_id %}">{% trans "View Detail"%}</a></button>
-                        </td>
-					</tr>
-					{% endfor %}
-				</tbody>
-                {% endif %}
-                </table>
-
-			    {% if is_paginated %}
-			        <div class="pagination">
-			            <span class="page-links">
-			                {% if page_obj.has_previous %}
-			                    <a href="{{request.path}}?page={{ page_obj.previous_page_number }}">{% trans "previous"%}</a>
-			                {% endif %}
-			                <span class="page-current">
-			                    Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
-			                </span>
-			                {% if page_obj.has_next %}
-			                    <a href="{{request.path}}?page={{ page_obj.next_page_number }}">{% trans "next"%}</a>
-			                {% endif %}
-			            </span>
-			        </div>
-			    {% endif %}
-			</div>
-
-	    </div>
-	</div>
-
-</div>
-{% endcomment %}
 {%endblock%}

From 337021a470541eacc22b832e21bc163735cbeb37 Mon Sep 17 00:00:00 2001
From: Arvind Tiwari <tiwariav@gmail.com>
Date: Wed, 16 Aug 2017 04:13:40 +0530
Subject: [PATCH 20/32] added other conditional components on page

---
 .../templates/hosting/virtual_machines.html   | 192 ++++++++++++++----
 1 file changed, 151 insertions(+), 41 deletions(-)

diff --git a/hosting/templates/hosting/virtual_machines.html b/hosting/templates/hosting/virtual_machines.html
index 2d033a8d..c792bc08 100644
--- a/hosting/templates/hosting/virtual_machines.html
+++ b/hosting/templates/hosting/virtual_machines.html
@@ -1,49 +1,159 @@
 {% extends "hosting/base_short.html" %}
 {% load staticfiles bootstrap3 i18n %}
-
 {% block content %}
 <div class="dashboard-container">
     <h3 class="dashboard-title-thin"><img src="{% static 'hosting/img/vm.svg' %}" class="un-icon"> {% trans "Virtual Machines" %}</h3>
-    <div class="dashboard-subtitle">
-        <p>{% trans 'To create a new virtual machine, click "Create VM"' %}</p>
-        <div class="text-right">
-            <a class="btn btn-vm" href="{% url 'hosting:create_virtual_machine' %}"><span class="css-plus"></span> <span>{% trans "CREATE VM"%}</span></a>
-        </div>
-    </div>
-
-    <table class="table table-switch">
-        <thead>
-            <tr>
-                <th>ID</th>
-                <th>Ipv4</th>
-                <th>Ipv6</th>
-                <th>{% trans "Status" %}</th>
-                <th></th>
-            </tr>
-        </thead>
-        <tbody>
-            {% for vm in vms %}
-            <tr>
-                <td data-header="ID">{{vm.vm_id}}</td>
-                {% if vm.ipv6  %}
-                    <td data-header="Ipv4">{{vm.ipv4}}</td>
-                    <td data-header="Ipv6">{{vm.ipv6}}</td>
-                {% endif %}
-                <td data-header="{% trans 'Status' %}">
-                    {% if vm.state == 'ACTIVE' %}
-                        <span class="vm-status-active"><strong>{{vm.state}}</strong></span>
-                    {% elif  vm.state == 'FAILED' %}
-                        <span class="vm-status-failed"><strong>{{vm.state}}</strong></span>
-                    {% else %}
-                        <span class="vm-status"><strong>{{vm.state}}</strong></span>
-                    {% endif %}
-                </td>
-                <td class="text-right last-td">
-                    <a class="btn btn-vm-detail" href="{% url 'hosting:virtual_machines' vm.vm_id %}">{% trans "View Detail"%}</a>
-                </td>
-            </tr>
+    {% if messages %}
+        <div class="alert alert-warning">
+            {% for message in messages %}
+            <span>{{ message }}</span>
             {% endfor %}
-        </tbody>
-    </table>
+        </div>
+    {% endif %}
+
+    {% if not error %}
+        <div class="dashboard-subtitle">
+            <p>{% trans 'To create a new virtual machine, click "Create VM"' %}</p>
+            <div class="text-right">
+                <a class="btn btn-vm" href="{% url 'hosting:create_virtual_machine' %}"><span class="css-plus"></span> <span>{% trans "CREATE VM"%}</span></a>
+            </div>
+        </div>
+        <table class="table table-switch">
+            <thead>
+                <tr>
+                    <th>ID</th>
+                    <th>Ipv4</th>
+                    <th>Ipv6</th>
+                    <th>{% trans "Status" %}</th>
+                    <th></th>
+                </tr>
+            </thead>
+            <tbody>
+                {% for vm in vms %}
+                <tr>
+                    <td data-header="ID">{{vm.vm_id}}</td>
+                    {% if vm.ipv6  %}
+                        <td data-header="Ipv4">{{vm.ipv4}}</td>
+                        <td data-header="Ipv6">{{vm.ipv6}}</td>
+                    {% endif %}
+                    <td data-header="{% trans 'Status' %}">
+                        {% if vm.state == 'ACTIVE' %}
+                            <span class="vm-status-active"><strong>{{vm.state}}</strong></span>
+                        {% elif  vm.state == 'FAILED' %}
+                            <span class="vm-status-failed"><strong>{{vm.state}}</strong></span>
+                        {% else %}
+                            <span class="vm-status"><strong>{{vm.state}}</strong></span>
+                        {% endif %}
+                    </td>
+                    <td class="text-right last-td">
+                        <a class="btn btn-vm-detail" href="{% url 'hosting:virtual_machines' vm.vm_id %}">{% trans "View Detail"%}</a>
+                    </td>
+                </tr>
+                {% endfor %}
+            </tbody>
+        </table>
+    {% endif %}
+
+    {% if is_paginated %}
+        <div class="pagination">
+            <span class="page-links">
+                {% if page_obj.has_previous %}
+                    <a href="{{request.path}}?page={{ page_obj.previous_page_number }}">{% trans "previous"%}</a>
+                {% endif %}
+                <span class="page-current">
+                    Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
+                </span>
+                {% if page_obj.has_next %}
+                    <a href="{{request.path}}?page={{ page_obj.next_page_number }}">{% trans "next"%}</a>
+                {% endif %}
+            </span>
+        </div>
+    {% endif %}
 </div>
+
+{% comment %}
+<div>
+	<div class="dashboard-container">
+		<div class="row">
+			<div class="col-xs-12  container-table">
+				<table class="table borderless table-hover">
+				<h3 class="pull-left"><i class="fa fa-server fa-separate" aria-hidden="true"></i> {% trans "Virtual Machines"%}</h3>
+                <div class="col-md-12">
+                    <br/>
+                    {% if messages %}
+                        <div class="alert alert-warning">
+                            {% for message in messages %}
+                            <span>{{ message }}</span>
+                            {% endfor %}
+                        </div>
+                    {% endif %}
+                </div>
+                {% if not error %}
+                <p class="pull-right btn-create-vm">
+                    <a class="btn btn-success" href="{% url 'hosting:create_virtual_machine' %}" >{% trans "Create VM"%} </a>
+                </p>
+				<br/>
+
+				<thead>
+				<tr>
+					<th>{% trans "ID"%}</th>
+                    <th>{% trans "Ipv4"%}</th>
+					<th>{% trans "Ipv6"%}</th>
+					<th>{% trans "Status"%}</th>
+					<th></th>
+				</tr>
+				</thead>
+				<tbody>
+					{% for vm in vms %}
+					<tr>
+						<td scope="row">{{vm.vm_id}}</td>
+                        {% if vm.ipv6  %}
+						  <td>{{vm.ipv4}}</td>
+
+                          <td>{{vm.ipv6}}</td>
+                        {% endif %}
+
+						<td>
+
+							{% if vm.state == 'ACTIVE' %}
+								<span class="h3 label label-success"><strong> {{vm.state}}</strong></span>
+							{% elif  vm.state == 'FAILED' %}
+								<span class="h3 label label-danger"><strong>{{vm.state}}</strong></span>
+							{% else %}
+								<span class="h3 label label-warning"><strong>{{vm.state}}</strong></span>
+							{% endif %}
+
+						</td>
+						<td>
+                            <button type="button" class="btn btn-default"><a
+                                    href="{% url 'hosting:virtual_machines' vm.vm_id %}">{% trans "View Detail"%}</a></button>
+                        </td>
+					</tr>
+					{% endfor %}
+				</tbody>
+                {% endif %}
+                </table>
+
+			    {% if is_paginated %}
+			        <div class="pagination">
+			            <span class="page-links">
+			                {% if page_obj.has_previous %}
+			                    <a href="{{request.path}}?page={{ page_obj.previous_page_number }}">{% trans "previous"%}</a>
+			                {% endif %}
+			                <span class="page-current">
+			                    Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
+			                </span>
+			                {% if page_obj.has_next %}
+			                    <a href="{{request.path}}?page={{ page_obj.next_page_number }}">{% trans "next"%}</a>
+			                {% endif %}
+			            </span>
+			        </div>
+			    {% endif %}
+			</div>
+
+	    </div>
+	</div>
+
+</div>
+{% endcomment %}
 {%endblock%}

From df97a16a26d1ac600308dd752c9aca2ac4f55fe8 Mon Sep 17 00:00:00 2001
From: Arvind Tiwari <tiwariav@gmail.com>
Date: Wed, 16 Aug 2017 04:14:46 +0530
Subject: [PATCH 21/32] removed old markup

---
 .../templates/hosting/virtual_machines.html   | 86 -------------------
 1 file changed, 86 deletions(-)

diff --git a/hosting/templates/hosting/virtual_machines.html b/hosting/templates/hosting/virtual_machines.html
index c792bc08..6964fb3a 100644
--- a/hosting/templates/hosting/virtual_machines.html
+++ b/hosting/templates/hosting/virtual_machines.html
@@ -70,90 +70,4 @@
         </div>
     {% endif %}
 </div>
-
-{% comment %}
-<div>
-	<div class="dashboard-container">
-		<div class="row">
-			<div class="col-xs-12  container-table">
-				<table class="table borderless table-hover">
-				<h3 class="pull-left"><i class="fa fa-server fa-separate" aria-hidden="true"></i> {% trans "Virtual Machines"%}</h3>
-                <div class="col-md-12">
-                    <br/>
-                    {% if messages %}
-                        <div class="alert alert-warning">
-                            {% for message in messages %}
-                            <span>{{ message }}</span>
-                            {% endfor %}
-                        </div>
-                    {% endif %}
-                </div>
-                {% if not error %}
-                <p class="pull-right btn-create-vm">
-                    <a class="btn btn-success" href="{% url 'hosting:create_virtual_machine' %}" >{% trans "Create VM"%} </a>
-                </p>
-				<br/>
-
-				<thead>
-				<tr>
-					<th>{% trans "ID"%}</th>
-                    <th>{% trans "Ipv4"%}</th>
-					<th>{% trans "Ipv6"%}</th>
-					<th>{% trans "Status"%}</th>
-					<th></th>
-				</tr>
-				</thead>
-				<tbody>
-					{% for vm in vms %}
-					<tr>
-						<td scope="row">{{vm.vm_id}}</td>
-                        {% if vm.ipv6  %}
-						  <td>{{vm.ipv4}}</td>
-
-                          <td>{{vm.ipv6}}</td>
-                        {% endif %}
-
-						<td>
-
-							{% if vm.state == 'ACTIVE' %}
-								<span class="h3 label label-success"><strong> {{vm.state}}</strong></span>
-							{% elif  vm.state == 'FAILED' %}
-								<span class="h3 label label-danger"><strong>{{vm.state}}</strong></span>
-							{% else %}
-								<span class="h3 label label-warning"><strong>{{vm.state}}</strong></span>
-							{% endif %}
-
-						</td>
-						<td>
-                            <button type="button" class="btn btn-default"><a
-                                    href="{% url 'hosting:virtual_machines' vm.vm_id %}">{% trans "View Detail"%}</a></button>
-                        </td>
-					</tr>
-					{% endfor %}
-				</tbody>
-                {% endif %}
-                </table>
-
-			    {% if is_paginated %}
-			        <div class="pagination">
-			            <span class="page-links">
-			                {% if page_obj.has_previous %}
-			                    <a href="{{request.path}}?page={{ page_obj.previous_page_number }}">{% trans "previous"%}</a>
-			                {% endif %}
-			                <span class="page-current">
-			                    Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
-			                </span>
-			                {% if page_obj.has_next %}
-			                    <a href="{{request.path}}?page={{ page_obj.next_page_number }}">{% trans "next"%}</a>
-			                {% endif %}
-			            </span>
-			        </div>
-			    {% endif %}
-			</div>
-
-	    </div>
-	</div>
-
-</div>
-{% endcomment %}
 {%endblock%}

From a2229d325052dd54ce785fd65659637c9d9bfdf5 Mon Sep 17 00:00:00 2001
From: Arvind Tiwari <tiwariav@gmail.com>
Date: Wed, 16 Aug 2017 04:26:17 +0530
Subject: [PATCH 22/32] created translations

---
 hosting/locale/de/LC_MESSAGES/django.po       | 24 ++++++++++++-------
 hosting/templates/hosting/user_keys.html      |  2 +-
 .../templates/hosting/virtual_machines.html   | 10 ++++----
 3 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/hosting/locale/de/LC_MESSAGES/django.po b/hosting/locale/de/LC_MESSAGES/django.po
index 39bc4adc..3cc30292 100644
--- a/hosting/locale/de/LC_MESSAGES/django.po
+++ b/hosting/locale/de/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-08-11 01:16+0530\n"
+"POT-Creation-Date: 2017-08-16 04:19+0530\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -435,17 +435,17 @@ msgstr "Sind Sie sicher, dass Sie ihre virtuelle Maschine beenden wollen "
 msgid "Virtual Machines"
 msgstr "Virtuelle Maschinen"
 
-msgid "Create VM"
-msgstr "Neue VM"
-
-msgid "ID"
+msgid "To create a new virtual machine, click \"Create VM\""
 msgstr ""
 
-msgid "Ipv4"
-msgstr "IPv4"
+msgid "CREATE VM"
+msgstr "NEUE VM"
 
-msgid "Ipv6"
-msgstr "IPv6"
+msgid "Page"
+msgstr ""
+
+msgid "of"
+msgstr ""
 
 msgid "login"
 msgstr "einloggen"
@@ -482,6 +482,12 @@ msgid ""
 "contact Data Center Light Support."
 msgstr ""
 
+#~ msgid "Ipv4"
+#~ msgstr "IPv4"
+
+#~ msgid "Ipv6"
+#~ msgstr "IPv6"
+
 #~ msgid "Close"
 #~ msgstr "Schliessen"
 
diff --git a/hosting/templates/hosting/user_keys.html b/hosting/templates/hosting/user_keys.html
index b66a1f6f..fd93b66f 100644
--- a/hosting/templates/hosting/user_keys.html
+++ b/hosting/templates/hosting/user_keys.html
@@ -77,7 +77,7 @@
                                         </button>
                                     </div>
                                     <div class="modal-body">
-                                        <h4 class="modal-title" id="ModalLabel_Public_Key">{% trans "Public SSH key" %}</h4>
+                                        <h4 class="modal-title" id="ModalLabel_Public_Key">{% trans "Public SSH Key" %}</h4>
                                         <p class="key_contain" style="margin-top: 10px;">{{ user_key.public_key }}</p>
                                         <div class="modal-footer">
                                         </div>
diff --git a/hosting/templates/hosting/virtual_machines.html b/hosting/templates/hosting/virtual_machines.html
index 6964fb3a..ccea2dcc 100644
--- a/hosting/templates/hosting/virtual_machines.html
+++ b/hosting/templates/hosting/virtual_machines.html
@@ -15,7 +15,7 @@
         <div class="dashboard-subtitle">
             <p>{% trans 'To create a new virtual machine, click "Create VM"' %}</p>
             <div class="text-right">
-                <a class="btn btn-vm" href="{% url 'hosting:create_virtual_machine' %}"><span class="css-plus"></span> <span>{% trans "CREATE VM"%}</span></a>
+                <a class="btn btn-vm" href="{% url 'hosting:create_virtual_machine' %}"><span class="css-plus"></span> <span>{% trans "CREATE VM" %}</span></a>
             </div>
         </div>
         <table class="table table-switch">
@@ -46,7 +46,7 @@
                         {% endif %}
                     </td>
                     <td class="text-right last-td">
-                        <a class="btn btn-vm-detail" href="{% url 'hosting:virtual_machines' vm.vm_id %}">{% trans "View Detail"%}</a>
+                        <a class="btn btn-vm-detail" href="{% url 'hosting:virtual_machines' vm.vm_id %}">{% trans "View Detail" %}</a>
                     </td>
                 </tr>
                 {% endfor %}
@@ -58,13 +58,13 @@
         <div class="pagination">
             <span class="page-links">
                 {% if page_obj.has_previous %}
-                    <a href="{{request.path}}?page={{ page_obj.previous_page_number }}">{% trans "previous"%}</a>
+                    <a href="{{request.path}}?page={{ page_obj.previous_page_number }}">{% trans "previous" %}</a>
                 {% endif %}
                 <span class="page-current">
-                    Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
+                    {% trans "Page" %} {{ page_obj.number }} {% trans "of" %} {{ page_obj.paginator.num_pages }}.
                 </span>
                 {% if page_obj.has_next %}
-                    <a href="{{request.path}}?page={{ page_obj.next_page_number }}">{% trans "next"%}</a>
+                    <a href="{{request.path}}?page={{ page_obj.next_page_number }}">{% trans "next" %}</a>
                 {% endif %}
             </span>
         </div>

From 079f0ed68d6f61c4ff7903a6c2923a1cbf423a1e Mon Sep 17 00:00:00 2001
From: Arvind Tiwari <tiwariav@gmail.com>
Date: Wed, 16 Aug 2017 20:35:14 +0530
Subject: [PATCH 23/32] status text capitalization changed to Titlecaps

---
 hosting/templates/hosting/virtual_machines.html | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hosting/templates/hosting/virtual_machines.html b/hosting/templates/hosting/virtual_machines.html
index ccea2dcc..c4c09108 100644
--- a/hosting/templates/hosting/virtual_machines.html
+++ b/hosting/templates/hosting/virtual_machines.html
@@ -38,11 +38,11 @@
                     {% endif %}
                     <td data-header="{% trans 'Status' %}">
                         {% if vm.state == 'ACTIVE' %}
-                            <span class="vm-status-active"><strong>{{vm.state}}</strong></span>
+                            <span class="vm-status-active"><strong>{{vm.state|title}}</strong></span>
                         {% elif  vm.state == 'FAILED' %}
-                            <span class="vm-status-failed"><strong>{{vm.state}}</strong></span>
+                            <span class="vm-status-failed"><strong>{{vm.state|title}}</strong></span>
                         {% else %}
-                            <span class="vm-status"><strong>{{vm.state}}</strong></span>
+                            <span class="vm-status"><strong>{{vm.state|title}}</strong></span>
                         {% endif %}
                     </td>
                     <td class="text-right last-td">

From b09477c8744b940c91a12724c9c8d1d614cdb899 Mon Sep 17 00:00:00 2001
From: Arvind Tiwari <tiwariav@gmail.com>
Date: Wed, 16 Aug 2017 20:41:55 +0530
Subject: [PATCH 24/32] text changed Ipv -> IPv

---
 hosting/templates/hosting/virtual_machines.html | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/hosting/templates/hosting/virtual_machines.html b/hosting/templates/hosting/virtual_machines.html
index c4c09108..fb9e400d 100644
--- a/hosting/templates/hosting/virtual_machines.html
+++ b/hosting/templates/hosting/virtual_machines.html
@@ -22,8 +22,8 @@
             <thead>
                 <tr>
                     <th>ID</th>
-                    <th>Ipv4</th>
-                    <th>Ipv6</th>
+                    <th>IPv4</th>
+                    <th>IPv6</th>
                     <th>{% trans "Status" %}</th>
                     <th></th>
                 </tr>
@@ -33,8 +33,8 @@
                 <tr>
                     <td data-header="ID">{{vm.vm_id}}</td>
                     {% if vm.ipv6  %}
-                        <td data-header="Ipv4">{{vm.ipv4}}</td>
-                        <td data-header="Ipv6">{{vm.ipv6}}</td>
+                        <td data-header="IPv4">{{vm.ipv4}}</td>
+                        <td data-header="IPv6">{{vm.ipv6}}</td>
                     {% endif %}
                     <td data-header="{% trans 'Status' %}">
                         {% if vm.state == 'ACTIVE' %}

From 5e5e33ce700ae0ee668c73abc1328597f8ec36e9 Mon Sep 17 00:00:00 2001
From: Arvind Tiwari <tiwariav@gmail.com>
Date: Fri, 18 Aug 2017 23:27:57 +0530
Subject: [PATCH 25/32] alignment and last item border

---
 .../static/hosting/css/virtual-machine.css    | 15 +++++++--
 .../templates/hosting/virtual_machines.html   | 32 +++++++++++--------
 2 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/hosting/static/hosting/css/virtual-machine.css b/hosting/static/hosting/css/virtual-machine.css
index 0dd89866..b9409712 100644
--- a/hosting/static/hosting/css/virtual-machine.css
+++ b/hosting/static/hosting/css/virtual-machine.css
@@ -230,6 +230,9 @@
 }
 
 /* New styles */
+.dashboard-container-head {
+  padding: 0 8px;
+}
 .dashboard-title-thin {
   font-weight: 300;
   font-size: 32px;
@@ -323,6 +326,10 @@
   padding: 12px 8px;
 }
 
+.table-switch > tbody > tr:last-child > td {
+  border-bottom: 1px solid #ddd;
+}
+
 @media (min-width: 768px) {
   .table-switch > tbody > tr > td:nth-child(1) {
     padding-right: 45px;
@@ -348,8 +355,12 @@
     display: block;
     position: relative;
     border-top: 1px solid #ddd;
-    margin-top: 15px;
+    /* margin-top: 15px; */
     padding-top: 5px;
+    padding-bottom: 15px;
+  }
+  .table-switch tbody tr:last-child {
+    border-bottom: 1px solid #ddd;
   }
   .table-switch tbody tr td {
     display: block;
@@ -367,7 +378,7 @@
   }
   .table-switch .last-td {
     position: absolute;
-    bottom: 5px;
+    bottom: 20px;
     right: 0;
   }
 }
\ No newline at end of file
diff --git a/hosting/templates/hosting/virtual_machines.html b/hosting/templates/hosting/virtual_machines.html
index fb9e400d..f7461abe 100644
--- a/hosting/templates/hosting/virtual_machines.html
+++ b/hosting/templates/hosting/virtual_machines.html
@@ -2,22 +2,26 @@
 {% load staticfiles bootstrap3 i18n %}
 {% block content %}
 <div class="dashboard-container">
-    <h3 class="dashboard-title-thin"><img src="{% static 'hosting/img/vm.svg' %}" class="un-icon"> {% trans "Virtual Machines" %}</h3>
-    {% if messages %}
-        <div class="alert alert-warning">
-            {% for message in messages %}
-            <span>{{ message }}</span>
-            {% endfor %}
-        </div>
-    {% endif %}
+    <div class="dashboard-container-head">
+        <h3 class="dashboard-title-thin"><img src="{% static 'hosting/img/vm.svg' %}" class="un-icon"> {% trans "Virtual Machines" %}</h3>
+        {% if messages %}
+            <div class="alert alert-warning">
+                {% for message in messages %}
+                <span>{{ message }}</span>
+                {% endfor %}
+            </div>
+        {% endif %}
+        {% if not error %}
+            <div class="dashboard-subtitle">
+                <p>{% trans 'To create a new virtual machine, click "Create VM"' %}</p>
+                <div class="text-right">
+                    <a class="btn btn-vm" href="{% url 'hosting:create_virtual_machine' %}"><span class="css-plus"></span> <span>{% trans "CREATE VM" %}</span></a>
+                </div>
+            </div>
+        {% endif %}
+    </div>
 
     {% if not error %}
-        <div class="dashboard-subtitle">
-            <p>{% trans 'To create a new virtual machine, click "Create VM"' %}</p>
-            <div class="text-right">
-                <a class="btn btn-vm" href="{% url 'hosting:create_virtual_machine' %}"><span class="css-plus"></span> <span>{% trans "CREATE VM" %}</span></a>
-            </div>
-        </div>
         <table class="table table-switch">
             <thead>
                 <tr>

From 3dc41edefbcd182ba807b3dc5105b1efc0b87bcf Mon Sep 17 00:00:00 2001
From: Arvind Tiwari <tiwariav@gmail.com>
Date: Fri, 18 Aug 2017 23:51:27 +0530
Subject: [PATCH 26/32] mobile border glitch solved

---
 hosting/static/hosting/css/virtual-machine.css | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/hosting/static/hosting/css/virtual-machine.css b/hosting/static/hosting/css/virtual-machine.css
index b9409712..420a9452 100644
--- a/hosting/static/hosting/css/virtual-machine.css
+++ b/hosting/static/hosting/css/virtual-machine.css
@@ -66,8 +66,8 @@
   overflow-x: hidden;
   overflow-y: hidden;
 }
-.parent-container ::-webkit-scrollbar { 
-    display: none; 
+.parent-container ::-webkit-scrollbar {
+    display: none;
 }
 .container-os{
   overflow: auto;
@@ -225,7 +225,7 @@
 }
 @media (max-width: 420px) {
     .btn-create-vm {
-      float: left !important; 
+      float: left !important;
     }
 }
 
@@ -326,14 +326,13 @@
   padding: 12px 8px;
 }
 
-.table-switch > tbody > tr:last-child > td {
-  border-bottom: 1px solid #ddd;
-}
-
 @media (min-width: 768px) {
   .table-switch > tbody > tr > td:nth-child(1) {
     padding-right: 45px;
   }
+  .table-switch > tbody > tr:last-child > td {
+    border-bottom: 1px solid #ddd;
+  }
 }
 
 .table-switch .un-icon {

From 819e7983927bdbd950c47b1a863dd099e8f6f7de Mon Sep 17 00:00:00 2001
From: PCoder <purple.coder@yahoo.co.uk>
Date: Sat, 19 Aug 2017 02:28:48 +0530
Subject: [PATCH 27/32] Update get_ipv4 and get_ipv6 for multiple nics +
 Reformatted code

---
 opennebula_api/serializers.py | 56 ++++++++++++++++++++++-------------
 1 file changed, 36 insertions(+), 20 deletions(-)

diff --git a/opennebula_api/serializers.py b/opennebula_api/serializers.py
index 12b313af..662b2fb6 100644
--- a/opennebula_api/serializers.py
+++ b/opennebula_api/serializers.py
@@ -1,5 +1,6 @@
 import ipaddress
 
+from builtins import hasattr
 from rest_framework import serializers
 
 from oca import OpenNebulaException
@@ -32,7 +33,7 @@ class VirtualMachineTemplateSerializer(serializers.Serializer):
             return 0
 
     def get_memory(self, obj):
-        return int(obj.template.memory)/1024
+        return int(obj.template.memory) / 1024
 
     def get_name(self, obj):
         return obj.name.strip('public-')
@@ -57,13 +58,13 @@ class VirtualMachineSerializer(serializers.Serializer):
     configuration = serializers.SerializerMethodField()
 
     template_id = serializers.ChoiceField(
-                choices=[(key.id, key.name) for key in
-                         OpenNebulaManager().try_get_templates()
-                         ],
-                source='template.template_id',
-                write_only=True,
-                default=[]
-            )
+        choices=[(key.id, key.name) for key in
+                 OpenNebulaManager().try_get_templates()
+                 ],
+        source='template.template_id',
+        write_only=True,
+        default=[]
+    )
 
     def create(self, validated_data):
         owner = validated_data['owner']
@@ -74,10 +75,10 @@ class VirtualMachineSerializer(serializers.Serializer):
 
         template_id = validated_data['template']['template_id']
         specs = {
-                    'cpu': cores,
-                    'disk_size': disk,
-                    'memory': memory,
-                }
+            'cpu': cores,
+            'disk_size': disk,
+            'memory': memory,
+        }
 
         try:
             manager = OpenNebulaManager(email=owner.email,
@@ -92,7 +93,7 @@ class VirtualMachineSerializer(serializers.Serializer):
         return manager.get_vm(opennebula_id)
 
     def get_memory(self, obj):
-        return int(obj.template.memory)/1024
+        return int(obj.template.memory) / 1024
 
     def get_disk_size(self, obj):
         template = obj.template
@@ -104,9 +105,9 @@ class VirtualMachineSerializer(serializers.Serializer):
     def get_price(self, obj):
         template = obj.template
         price = float(template.vcpu) * 5.0
-        price += (int(template.memory)/1024 * 2.0)
+        price += (int(template.memory) / 1024 * 2.0)
         for disk in template.disks:
-            price += int(disk.size)/1024 * 0.6
+            price += int(disk.size) / 1024 * 0.6
         return price
 
     def get_configuration(self, obj):
@@ -115,15 +116,30 @@ class VirtualMachineSerializer(serializers.Serializer):
         return template.name.strip('public-')
 
     def get_ipv4(self, obj):
-        nic = obj.template.nics[0]
-        if 'vm-ipv6-nat64-ipv4' in nic.network and is_in_v4_range(nic.mac):
-            return str(v4_from_mac(nic.mac))
+        """
+        Get the IPv4s from the given VM
+
+        :param obj: The VM in contention
+        :return: Returns csv string of all IPv4s added to this VM otherwise returns "-" if no IPv4 is available
+        """
+        ipv4 = []
+        for nic in obj.template.nics:
+            if hasattr(nic, 'ip'):
+                ipv4.append(nic.ip)
+        if len(ipv4) > 0:
+            return ', '.join(ipv4)
         else:
             return '-'
 
     def get_ipv6(self, obj):
-        nic = obj.template.nics[0]
-        return nic.ip6_global
+        ipv6 = []
+        for nic in obj.template.nics:
+            if hasattr(nic, 'ip6_global'):
+                ipv6.append(nic.ip6_global)
+        if len(ipv6) > 0:
+            return ', '.join(ipv6)
+        else:
+            return '-'
 
     def get_name(self, obj):
         return obj.name.strip('public-')

From 339a6283cd38694c144dc9cf670e9fc71b35a95d Mon Sep 17 00:00:00 2001
From: PCoder <purple.coder@yahoo.co.uk>
Date: Sat, 19 Aug 2017 03:32:30 +0530
Subject: [PATCH 28/32] Removed unused imports

---
 datacenterlight/views.py | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/datacenterlight/views.py b/datacenterlight/views.py
index dec5add6..db7f2e53 100644
--- a/datacenterlight/views.py
+++ b/datacenterlight/views.py
@@ -4,7 +4,6 @@ from .forms import BetaAccessForm
 from .models import BetaAccess, BetaAccessVMType, BetaAccessVM, VMTemplate
 from django.contrib import messages
 from django.core.urlresolvers import reverse
-from django.core.mail import EmailMessage
 from utils.mailer import BaseEmail
 from django.shortcuts import render
 from django.shortcuts import redirect
@@ -13,14 +12,13 @@ from django.core.exceptions import ValidationError
 from django.views.decorators.cache import cache_control
 from django.conf import settings
 from django.utils.translation import ugettext_lazy as _
-from utils.forms import BillingAddressForm, UserBillingAddressForm
+from utils.forms import BillingAddressForm
 from utils.models import BillingAddress
-from hosting.models import HostingOrder, HostingBill
+from hosting.models import HostingOrder
 from utils.stripe_utils import StripeUtils
-from datetime import datetime
 from membership.models import CustomUser, StripeCustomer
 from opennebula_api.models import OpenNebulaManager
-from opennebula_api.serializers import VirtualMachineTemplateSerializer, VirtualMachineSerializer, VMTemplateSerializer
+from opennebula_api.serializers import VirtualMachineTemplateSerializer, VMTemplateSerializer
 from datacenterlight.tasks import create_vm_task
 
 
@@ -445,8 +443,6 @@ class OrderConfirmationView(DetailView):
         customer = StripeCustomer.objects.filter(id=stripe_customer_id).first()
         billing_address_data = request.session.get('billing_address_data')
         billing_address_id = request.session.get('billing_address')
-        billing_address = BillingAddress.objects.filter(
-            id=billing_address_id).first()
         vm_template_id = template.get('id', 1)
         final_price = specs.get('price')
 

From 2b717954312483b2064db7a9c03eb5ee12c79059 Mon Sep 17 00:00:00 2001
From: PCoder <purple.coder@yahoo.co.uk>
Date: Sat, 19 Aug 2017 18:02:55 +0530
Subject: [PATCH 29/32] Added missing oneadmin's ssh key statement

---
 datacenterlight/tasks.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py
index dc71fcee..ee3b50c0 100644
--- a/datacenterlight/tasks.py
+++ b/datacenterlight/tasks.py
@@ -58,6 +58,7 @@ def create_vm_task(self, vm_template_id, user, specs, template, stripe_customer_
         vm_id = manager.create_vm(
             template_id=vm_template_id,
             specs=specs,
+            ssh_key=settings.ONEADMIN_USER_SSH_PUBLIC_KEY,
             vm_name="{email}-{template_name}-{date}".format(
                 email=user.get('email'),
                 template_name=template.get('name'),

From 422b0ca93e18d551ea69cf067f39136dc56575a7 Mon Sep 17 00:00:00 2001
From: PCoder <purple.coder@yahoo.co.uk>
Date: Sat, 19 Aug 2017 18:28:17 +0530
Subject: [PATCH 30/32] Updated deploy.sh     - Added --dbmakemigrations to do
 makemigrations     - Added call to restart celery

---
 deploy.sh | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/deploy.sh b/deploy.sh
index f2a1d59e..0ce17c39 100755
--- a/deploy.sh
+++ b/deploy.sh
@@ -13,6 +13,7 @@ while true; do
   case "$1" in
     -h | --help ) HELP=true; shift ;;
     -v | --verbose ) VERBOSE=true; shift ;;
+    -D | --dbmakemigrations ) DB_MAKE_MIGRATIONS=true; shift ;;
     -d | --dbmigrate ) DB_MIGRATE=true; shift ;;
     -n | --nogit ) NO_GIT=true; shift ;;
     -b | --branch ) BRANCH="$2"; shift 2 ;;
@@ -31,13 +32,15 @@ if [ "$HELP" == "true" ]; then
     echo "options are : "
     echo "        -h, --help: Print this help message"
     echo "        -v, --verbose: Show verbose output to stdout. Without this a deploy.log is written to ~/app folder"
-    echo "        -d, --dbmigrate: Do DB migrate"
-    echo "        -n, --nogit: Don't execute git commands. With this --branch has no effect."
+    echo "        -D, --dbmakemigrations: Do DB makemigrations"
+    echo "        -d, --dbmigrate: Do DB migrate. To do both makemigrations and migrate, supply both switches -D and -d"
+    echo "        -n, --nogit: Don't execute git commands. This is used to deploy the current code in the project repo. With this --branch has no effect."
     echo "        -b, --branch: The branch to pull from origin repo."
     exit
 fi
 
 echo "BRANCH="$BRANCH
+echo "DB_MAKE_MIGRATIONS="$DB_MAKE_MIGRATIONS
 echo "DB_MIGRATE="$DB_MIGRATE
 echo "NO_GIT="$NO_GIT
 echo "VERBOSE="$VERBOSE
@@ -45,7 +48,7 @@ echo "VERBOSE="$VERBOSE
 # The project directory exists, we pull the specified branch
 cd $APP_HOME_DIR
 if [ -z "$NO_GIT" ]; then
-    echo 'We are executing default git commands. Please -no_git to not use this.'
+    echo 'We are executing default git commands. Please add --nogit to not do this.'
     # Save any modified changes before git pulling
     git stash
     # Fetch all branches/tags
@@ -59,16 +62,23 @@ fi
 source ~/pyvenv/bin/activate
 pip install -r requirements.txt > deploy.log 2>&1
 echo "###" >> deploy.log
+if [ -z "$DB_MAKE_MIGRATIONS" ]; then
+    echo 'We are not doing DB makemigrations'
+else
+    echo 'Doing DB makemigrations'
+    ./manage.py makemigrations >> deploy.log 2>&1
+    echo "###" >> deploy.log
+fi
 if [ -z "$DB_MIGRATE" ]; then
     echo 'We are not doing DB migration'
 else
-    ./manage.py makemigrations >> deploy.log 2>&1
-    echo "###" >> deploy.log
+    echo 'Doing DB migrate'
     ./manage.py migrate >> deploy.log 2>&1
     echo "###" >> deploy.log
 fi
 printf 'yes' | ./manage.py collectstatic >> deploy.log 2>&1
 echo "###" >> deploy.log
 django-admin compilemessages
+sudo systemctl restart celery.service
 sudo systemctl restart uwsgi
 

From 777102c387fb01a98d3447e28cef80b49689527f Mon Sep 17 00:00:00 2001
From: PCoder <purple.coder@yahoo.co.uk>
Date: Sat, 19 Aug 2017 18:32:58 +0530
Subject: [PATCH 31/32] Updated deploy.sh: corrected terminology

---
 deploy.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/deploy.sh b/deploy.sh
index 0ce17c39..04a7b04c 100755
--- a/deploy.sh
+++ b/deploy.sh
@@ -70,7 +70,7 @@ else
     echo "###" >> deploy.log
 fi
 if [ -z "$DB_MIGRATE" ]; then
-    echo 'We are not doing DB migration'
+    echo 'We are not doing DB migrate'
 else
     echo 'Doing DB migrate'
     ./manage.py migrate >> deploy.log 2>&1

From ddbaf902afbfaa0bd006a79febfcc8dbe3eb8414 Mon Sep 17 00:00:00 2001
From: PCoder <purple.coder@yahoo.co.uk>
Date: Sun, 20 Aug 2017 20:23:59 +0530
Subject: [PATCH 32/32] Removed __future__ datacenterlight/tasks

---
 datacenterlight/tasks.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py
index ee3b50c0..b897c54a 100644
--- a/datacenterlight/tasks.py
+++ b/datacenterlight/tasks.py
@@ -1,4 +1,3 @@
-from __future__ import absolute_import, unicode_literals
 from dynamicweb.celery import app
 from celery.utils.log import get_task_logger
 from django.conf import settings