diff --git a/Changelog b/Changelog index d616964f..499fd781 100644 --- a/Changelog +++ b/Changelog @@ -1,4 +1,5 @@ Next: + * #4890: [hosting] Manage SSH keys using IPv6 of the VM (PR #640) * bugfix: Fix flake8 error that was ignored in release 1.9.1 1.9.1: 2018-06-24 * #4799: [dcl] Show selected vm templates only in calculator (PR #638) diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py index 3554580f..259a2e36 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 @@ -10,14 +10,15 @@ from django.utils import translation from django.utils.translation import ugettext_lazy as _ from dynamicweb.celery import app -from hosting.models import HostingOrder -from membership.models import CustomUser +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.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 utils.stripe_utils import StripeUtils - from .models import VMPricing logger = get_task_logger(__name__) @@ -186,11 +187,11 @@ def create_vm_task(self, vm_template_id, user, specs, template, order_id): 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_ipv4(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: @@ -201,13 +202,15 @@ def create_vm_task(self, vm_template_id, user, specs, template, order_id): 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 35f3d8e8..29632009 100644 --- a/opennebula_api/models.py +++ b/opennebula_api/models.py @@ -53,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 @@ -218,32 +209,31 @@ class OpenNebulaManager(): except: raise ConnectionRefusedError - def get_primary_ipv4(self, vm_id): + def get_ipv6(self, vm_id): """ - Returns the primary IPv4 of the given vm. - To be changed later. + Returns the first IPv6 of the given vm. - :return: An IP address string, if it exists else returns None + :return: An IPv6 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] + ipv6_list = self.get_all_ipv6_addresses(vm_id) + if len(ipv6_list) > 0: + return ipv6_list[0] else: return None - def get_vm_ipv4_addresses(self, vm_id): + def get_all_ipv6_addresses(self, vm_id): """ - Returns a list of IPv4 addresses of the given vm + Returns a list of IPv6 addresses of the given vm :param vm_id: The ID of the vm :return: """ - ipv4s = [] + ipv6_list = [] vm = self.get_vm(vm_id) for nic in vm.template.nics: - if hasattr(nic, 'ip'): - ipv4s.append(nic.ip) - return ipv4s + if hasattr(nic, 'ip6_global'): + ipv6_list.append(nic.ip6_global) + return ipv6_list def create_vm(self, template_id, specs, ssh_key=None, vm_name=None): @@ -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( @@ -547,7 +538,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: @@ -560,12 +551,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() @@ -576,10 +569,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'): - hosts.append(nic.ip) + ip = self.get_ipv6(order.vm_id) + hosts.append(ip) except WrongIdError: logger.debug( "VM with ID {} does not exist".format(order.vm_id))