From 6c2eabbe6af3880c6ea4e09aa9baf33111e0d72a Mon Sep 17 00:00:00 2001 From: PCoder Date: Wed, 27 Jun 2018 00:01:50 +0200 Subject: [PATCH 1/9] Use the public ipv4 if it exists; otherwise use the ipv6 to do a cdist cdist ssh configure --- datacenterlight/tasks.py | 2 +- opennebula_api/models.py | 59 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py index db479b43..07d132e2 100644 --- a/datacenterlight/tasks.py +++ b/datacenterlight/tasks.py @@ -190,7 +190,7 @@ def create_vm_task(self, vm_template_id, user, specs, template, # try to see if we have the IP and that if the ssh keys can # be configured - new_host = manager.get_primary_ipv4(vm_id) + new_host = manager.get_primary_ip(vm_id) logger.debug("New VM ID is {vm_id}".format(vm_id=vm_id)) if new_host is not None: custom_user = CustomUser.objects.get(email=user.get('email')) diff --git a/opennebula_api/models.py b/opennebula_api/models.py index 35f3d8e8..d573d6d5 100644 --- a/opennebula_api/models.py +++ b/opennebula_api/models.py @@ -218,6 +218,59 @@ class OpenNebulaManager(): except: raise ConnectionRefusedError + def is_public_ipv4(self, ipv4): + """ + Checks whether the passed ipv4 is a public IP. + + :param ipv4: + :return: Returns true if it is a public IP else returns false + """ + if ipv4.startswith("10."): + return False + else: + return True + + def get_primary_ip(self, vm_id): + """ + Returns primary ipv4 if it exists and is a public ip. Otherwise returns + the IPv6 of the machine + + :param vm_id: + :return: + """ + ipv4 = self.get_primary_ipv4(vm_id) + if self.is_public_ipv4(ipv4): + return ipv4 + else: + return self.get_primary_ipv6(vm_id) + + def get_primary_ipv6(self, vm_id): + """ + Returns the primary IPv6 of the given vm. + For now, we return the first available IPv6 (to be changed later) + + :return: An IP address string, if it exists else returns None + """ + all_ipv4s = self.get_vm_ipv4_addresses(vm_id) + if len(all_ipv4s) > 0: + return all_ipv4s[0] + else: + return None + + def get_vm_ipv6_addresses(self, vm_id): + """ + Returns a list of IPv6 addresses of the given vm + + :param vm_id: The ID of the vm + :return: + """ + ipv6s = [] + vm = self.get_vm(vm_id) + for nic in vm.template.nics: + if hasattr(nic, 'ip6_global'): + ipv6s.append(nic.ip6_global) + return ipv6s + def get_primary_ipv4(self, vm_id): """ Returns the primary IPv4 of the given vm. @@ -579,7 +632,11 @@ class OpenNebulaManager(): vm = self.get_vm(order.vm_id) for nic in vm.template.nics: if hasattr(nic, 'ip'): - hosts.append(nic.ip) + if str(nic.ip).startswith("10."): + if hasattr(nic, 'ip6_global'): + hosts.append(nic.ip6_global) + else: + hosts.append(nic.ip) except WrongIdError: logger.debug( "VM with ID {} does not exist".format(order.vm_id)) From 1ec7cb876168a06a89597c3d9160b264271a4092 Mon Sep 17 00:00:00 2001 From: PCoder Date: Wed, 27 Jun 2018 00:44:17 +0200 Subject: [PATCH 2/9] Fix silly copy/paste bug --- opennebula_api/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opennebula_api/models.py b/opennebula_api/models.py index d573d6d5..0cc870c3 100644 --- a/opennebula_api/models.py +++ b/opennebula_api/models.py @@ -251,9 +251,9 @@ class OpenNebulaManager(): :return: An IP address string, if it exists else returns None """ - all_ipv4s = self.get_vm_ipv4_addresses(vm_id) - if len(all_ipv4s) > 0: - return all_ipv4s[0] + all_ipv6s = self.get_vm_ipv6_addresses(vm_id) + if len(all_ipv6s) > 0: + return all_ipv6s[0] else: return None From 4a5c5f79425341ede31eac3b7878a6f5212183b3 Mon Sep 17 00:00:00 2001 From: PCoder Date: Wed, 27 Jun 2018 01:06:10 +0200 Subject: [PATCH 3/9] Refactor getting primary ip of a vm --- opennebula_api/models.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/opennebula_api/models.py b/opennebula_api/models.py index 0cc870c3..5416b6f2 100644 --- a/opennebula_api/models.py +++ b/opennebula_api/models.py @@ -629,14 +629,8 @@ class OpenNebulaManager(): "the ssh keys.".format(self.email)) for order in all_orders: try: - vm = self.get_vm(order.vm_id) - for nic in vm.template.nics: - if hasattr(nic, 'ip'): - if str(nic.ip).startswith("10."): - if hasattr(nic, 'ip6_global'): - hosts.append(nic.ip6_global) - else: - hosts.append(nic.ip) + ip = self.get_primary_ip(order.vm_id) + hosts.append(ip) except WrongIdError: logger.debug( "VM with ID {} does not exist".format(order.vm_id)) From 68a65b7bc73056364673dac63c90dfd8b377f5b5 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sat, 30 Jun 2018 00:30:51 +0200 Subject: [PATCH 4/9] Detect private IP correctly --- opennebula_api/models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opennebula_api/models.py b/opennebula_api/models.py index 5416b6f2..c06d790e 100644 --- a/opennebula_api/models.py +++ b/opennebula_api/models.py @@ -1,3 +1,4 @@ +import ipaddress import logging import socket @@ -225,7 +226,7 @@ class OpenNebulaManager(): :param ipv4: :return: Returns true if it is a public IP else returns false """ - if ipv4.startswith("10."): + if ipaddress.ip_address(ipv4).is_private: return False else: return True From 52e53d479ecfeb729d6c68ab45e0e3d94a333169 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 1 Jul 2018 07:57:15 +0200 Subject: [PATCH 5/9] Rename a variable: ipv6s -> ipv6_list --- opennebula_api/models.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/opennebula_api/models.py b/opennebula_api/models.py index c06d790e..3b69d91d 100644 --- a/opennebula_api/models.py +++ b/opennebula_api/models.py @@ -252,9 +252,9 @@ class OpenNebulaManager(): :return: An IP address string, if it exists else returns None """ - all_ipv6s = self.get_vm_ipv6_addresses(vm_id) - if len(all_ipv6s) > 0: - return all_ipv6s[0] + ipv6_list = self.get_vm_ipv6_addresses(vm_id) + if len(ipv6_list) > 0: + return ipv6_list[0] else: return None @@ -265,12 +265,12 @@ class OpenNebulaManager(): :param vm_id: The ID of the vm :return: """ - ipv6s = [] + ipv6_list = [] vm = self.get_vm(vm_id) for nic in vm.template.nics: if hasattr(nic, 'ip6_global'): - ipv6s.append(nic.ip6_global) - return ipv6s + ipv6_list.append(nic.ip6_global) + return ipv6_list def get_primary_ipv4(self, vm_id): """ From 8993a7bde1a13f37648787c2488e5218331b6307 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 1 Jul 2018 11:05:23 +0200 Subject: [PATCH 6/9] Reorganize imports + format code --- datacenterlight/tasks.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py index 07d132e2..4d0fa070 100644 --- a/datacenterlight/tasks.py +++ b/datacenterlight/tasks.py @@ -1,8 +1,8 @@ from datetime import datetime +from celery import current_task from celery.exceptions import MaxRetriesExceededError from celery.utils.log import get_task_logger -from celery import current_task from django.conf import settings from django.core.mail import EmailMessage from django.core.urlresolvers import reverse @@ -14,11 +14,10 @@ from hosting.models import HostingOrder, HostingBill from membership.models import StripeCustomer, CustomUser from opennebula_api.models import OpenNebulaManager from opennebula_api.serializers import VirtualMachineSerializer -from utils.hosting_utils import get_all_public_keys, get_or_create_vm_detail from utils.forms import UserBillingAddressForm +from utils.hosting_utils import get_all_public_keys, get_or_create_vm_detail from utils.mailer import BaseEmail from utils.models import BillingAddress - from .models import VMPricing logger = get_task_logger(__name__) @@ -173,8 +172,8 @@ def create_vm_task(self, vm_template_id, user, specs, template, 'order_url': reverse('hosting:orders', kwargs={'pk': order.id}), 'page_header': _( - 'Your New VM %(vm_name)s at Data Center Light') % { - 'vm_name': vm.get('name')}, + 'Your New VM %(vm_name)s at Data Center Light') % + {'vm_name': vm.get('name')}, 'vm_name': vm.get('name') } email_data = { From c13af950179bef9c8fb408e9c22d1df0dcefc699 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 1 Jul 2018 11:07:29 +0200 Subject: [PATCH 7/9] Refactor code: get_primary_ip -> get_ipv6 and remove unwanted code --- datacenterlight/tasks.py | 18 +++++----- opennebula_api/models.py | 74 ++++++---------------------------------- 2 files changed, 21 insertions(+), 71 deletions(-) diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py index 4d0fa070..b220cc38 100644 --- a/datacenterlight/tasks.py +++ b/datacenterlight/tasks.py @@ -187,11 +187,11 @@ def create_vm_task(self, vm_template_id, user, specs, template, email = BaseEmail(**email_data) email.send() - # try to see if we have the IP and that if the ssh keys can - # be configured - new_host = manager.get_primary_ip(vm_id) + # try to see if we have the IPv6 of the new vm and that if the ssh + # keys can be configured + vm_ipv6 = manager.get_ipv6(vm_id) logger.debug("New VM ID is {vm_id}".format(vm_id=vm_id)) - if new_host is not None: + if vm_ipv6 is not None: custom_user = CustomUser.objects.get(email=user.get('email')) get_or_create_vm_detail(custom_user, manager, vm_id) if custom_user is not None: @@ -202,13 +202,15 @@ def create_vm_task(self, vm_template_id, user, specs, template, logger.debug( "Calling configure on {host} for " "{num_keys} keys".format( - host=new_host, num_keys=len(keys))) + host=vm_ipv6, num_keys=len(keys) + ) + ) # Let's delay the task by 75 seconds to be sure # that we run the cdist configure after the host # is up - manager.manage_public_key(keys, - hosts=[new_host], - countdown=75) + manager.manage_public_key( + keys, hosts=[vm_ipv6], countdown=75 + ) except Exception as e: logger.error(str(e)) try: diff --git a/opennebula_api/models.py b/opennebula_api/models.py index 3b69d91d..d6811349 100644 --- a/opennebula_api/models.py +++ b/opennebula_api/models.py @@ -219,46 +219,19 @@ class OpenNebulaManager(): except: raise ConnectionRefusedError - def is_public_ipv4(self, ipv4): + def get_ipv6(self, vm_id): """ - Checks whether the passed ipv4 is a public IP. + Returns the first IPv6 of the given vm. - :param ipv4: - :return: Returns true if it is a public IP else returns false + :return: An IPv6 address string, if it exists else returns None """ - if ipaddress.ip_address(ipv4).is_private: - return False - else: - return True - - def get_primary_ip(self, vm_id): - """ - Returns primary ipv4 if it exists and is a public ip. Otherwise returns - the IPv6 of the machine - - :param vm_id: - :return: - """ - ipv4 = self.get_primary_ipv4(vm_id) - if self.is_public_ipv4(ipv4): - return ipv4 - else: - return self.get_primary_ipv6(vm_id) - - def get_primary_ipv6(self, vm_id): - """ - Returns the primary IPv6 of the given vm. - For now, we return the first available IPv6 (to be changed later) - - :return: An IP address string, if it exists else returns None - """ - ipv6_list = self.get_vm_ipv6_addresses(vm_id) + ipv6_list = self.get_all_ipv6_addresses(vm_id) if len(ipv6_list) > 0: return ipv6_list[0] else: return None - def get_vm_ipv6_addresses(self, vm_id): + def get_all_ipv6_addresses(self, vm_id): """ Returns a list of IPv6 addresses of the given vm @@ -272,33 +245,6 @@ class OpenNebulaManager(): ipv6_list.append(nic.ip6_global) return ipv6_list - def get_primary_ipv4(self, vm_id): - """ - Returns the primary IPv4 of the given vm. - To be changed later. - - :return: An IP address string, if it exists else returns None - """ - all_ipv4s = self.get_vm_ipv4_addresses(vm_id) - if len(all_ipv4s) > 0: - return all_ipv4s[0] - else: - return None - - def get_vm_ipv4_addresses(self, vm_id): - """ - Returns a list of IPv4 addresses of the given vm - - :param vm_id: The ID of the vm - :return: - """ - ipv4s = [] - vm = self.get_vm(vm_id) - for nic in vm.template.nics: - if hasattr(nic, 'ip'): - ipv4s.append(nic.ip) - return ipv4s - def create_vm(self, template_id, specs, ssh_key=None, vm_name=None): template = self.get_template(template_id) @@ -601,7 +547,7 @@ class OpenNebulaManager(): 'value': 'sha-.....', # public key as string 'state': True # whether key is to be added or } # removed - :param hosts: A list of hosts IP addresses + :param hosts: A list of hosts IPv6 addresses :param countdown: Parameter to be passed to celery apply_async Allows to delay a task by `countdown` number of seconds :return: @@ -614,12 +560,14 @@ class OpenNebulaManager(): link_error=save_ssh_key_error_handler.s()) else: logger.debug( - "Keys and/or hosts are empty, so not managing any keys") + "Keys and/or hosts are empty, so not managing any keys" + ) def get_all_hosts(self): """ A utility function to obtain all hosts of this owner - :return: A list of hosts IP addresses, empty if none exist + :return: A list of IPv6 addresses of all the hosts of this customer or + an empty list if none exist """ owner = CustomUser.objects.filter( email=self.email).first() @@ -630,7 +578,7 @@ class OpenNebulaManager(): "the ssh keys.".format(self.email)) for order in all_orders: try: - ip = self.get_primary_ip(order.vm_id) + ip = self.get_ipv6(order.vm_id) hosts.append(ip) except WrongIdError: logger.debug( From ae0d4c0841d10a0d459bcdfd993f0727368cdbd0 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 1 Jul 2018 11:17:45 +0200 Subject: [PATCH 8/9] Refactor code --- opennebula_api/models.py | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/opennebula_api/models.py b/opennebula_api/models.py index d6811349..29632009 100644 --- a/opennebula_api/models.py +++ b/opennebula_api/models.py @@ -1,4 +1,3 @@ -import ipaddress import logging import socket @@ -54,27 +53,18 @@ class OpenNebulaManager(): ConnectionError: If the connection to the opennebula server can't be established """ - return oca.Client("{0}:{1}".format( - user.email, - user.password), - "{protocol}://{domain}:{port}{endpoint}".format( - protocol=settings.OPENNEBULA_PROTOCOL, - domain=settings.OPENNEBULA_DOMAIN, - port=settings.OPENNEBULA_PORT, - endpoint=settings.OPENNEBULA_ENDPOINT - )) + return self._get_opennebula_client(user.email, user.password) def _get_opennebula_client(self, username, password): - return oca.Client("{0}:{1}".format( - username, - - password), + return oca.Client( + "{0}:{1}".format(username, password), "{protocol}://{domain}:{port}{endpoint}".format( protocol=settings.OPENNEBULA_PROTOCOL, domain=settings.OPENNEBULA_DOMAIN, port=settings.OPENNEBULA_PORT, endpoint=settings.OPENNEBULA_ENDPOINT - )) + ) + ) def _get_user(self, user): """Get the corresponding opennebula user for a CustomUser object @@ -438,8 +428,9 @@ class OpenNebulaManager(): return template_id def delete_template(self, template_id): - self.oneadmin_client.call(oca.VmTemplate.METHODS[ - 'delete'], template_id, False) + self.oneadmin_client.call( + oca.VmTemplate.METHODS['delete'], template_id, False + ) def change_user_password(self, passwd_hash): self.oneadmin_client.call( From ef8e380ab7a0884be9645076e134910ebd1fa5f9 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 1 Jul 2018 11:22:42 +0200 Subject: [PATCH 9/9] Fix flake8 error --- datacenterlight/tasks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py index b220cc38..22ee29ad 100644 --- a/datacenterlight/tasks.py +++ b/datacenterlight/tasks.py @@ -172,8 +172,8 @@ def create_vm_task(self, vm_template_id, user, specs, template, 'order_url': reverse('hosting:orders', kwargs={'pk': order.id}), 'page_header': _( - 'Your New VM %(vm_name)s at Data Center Light') % - {'vm_name': vm.get('name')}, + 'Your New VM %(vm_name)s at Data Center Light') % { + 'vm_name': vm.get('name')}, 'vm_name': vm.get('name') } email_data = {