| 
									
										
										
										
											2017-05-12 12:13:18 -05:00
										 |  |  | import logging | 
					
						
							| 
									
										
										
										
											2017-08-31 12:54:08 +05:30
										 |  |  | import socket | 
					
						
							| 
									
										
										
										
											2017-05-12 12:13:18 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-31 12:54:08 +05:30
										 |  |  | import oca | 
					
						
							| 
									
										
										
										
											2017-05-09 16:33:56 +02:00
										 |  |  | from django.conf import settings | 
					
						
							| 
									
										
										
										
											2017-08-31 12:54:08 +05:30
										 |  |  | from oca.exceptions import OpenNebulaException | 
					
						
							|  |  |  | from oca.pool import WrongNameError, WrongIdError | 
					
						
							| 
									
										
										
										
											2017-05-09 16:33:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-29 18:02:56 +02:00
										 |  |  | from hosting.models import HostingOrder | 
					
						
							| 
									
										
										
										
											2017-08-31 12:54:08 +05:30
										 |  |  | from utils.models import CustomUser | 
					
						
							| 
									
										
										
										
											2017-09-01 02:33:31 +05:30
										 |  |  | from utils.tasks import save_ssh_key, save_ssh_key_error_handler | 
					
						
							| 
									
										
										
										
											2017-08-31 12:54:08 +05:30
										 |  |  | from .exceptions import KeyExistsError, UserExistsError, UserCredentialError | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-12 12:13:18 -05:00
										 |  |  | logger = logging.getLogger(__name__) | 
					
						
							| 
									
										
										
										
											2017-05-10 04:06:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-09 16:33:56 +02:00
										 |  |  | class OpenNebulaManager(): | 
					
						
							|  |  |  |     """This class represents an opennebula manager.""" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-13 05:50:56 +02:00
										 |  |  |     def __init__(self, email=None, password=None): | 
					
						
							| 
									
										
										
										
											2017-08-31 12:54:08 +05:30
										 |  |  |         self.email = email | 
					
						
							|  |  |  |         self.password = password | 
					
						
							| 
									
										
										
										
											2017-05-09 16:33:56 +02:00
										 |  |  |         # Get oneadmin client | 
					
						
							|  |  |  |         self.oneadmin_client = self._get_opennebula_client( | 
					
						
							|  |  |  |             settings.OPENNEBULA_USERNAME, | 
					
						
							|  |  |  |             settings.OPENNEBULA_PASSWORD | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-09 16:33:56 +02:00
										 |  |  |         # Get or create oppenebula user using given credentials | 
					
						
							| 
									
										
										
										
											2017-05-13 05:50:56 +02:00
										 |  |  |         try: | 
					
						
							|  |  |  |             self.opennebula_user = self._get_or_create_user( | 
					
						
							|  |  |  |                 email, | 
					
						
							|  |  |  |                 password | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             # If opennebula user was created/obtained, get his client | 
					
						
							| 
									
										
										
										
											2017-05-09 16:33:56 +02:00
										 |  |  |             self.client = self._get_opennebula_client( | 
					
						
							|  |  |  |                 email, | 
					
						
							|  |  |  |                 password | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2017-05-13 05:50:56 +02:00
										 |  |  |         except: | 
					
						
							|  |  |  |             pass | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  |     def _get_client(self, user): | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |         """Get a opennebula client object for a CustomUser object
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  |         Args: | 
					
						
							|  |  |  |             user (CustomUser): dynamicweb CustomUser object | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Returns: | 
					
						
							|  |  |  |             oca.Client: Opennebula client object | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Raise: | 
					
						
							|  |  |  |             ConnectionError: If the connection to the opennebula server can't be | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |                 established | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         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 | 
					
						
							| 
									
										
										
										
											2017-07-26 19:41:05 +02:00
										 |  |  |             )) | 
					
						
							| 
									
										
										
										
											2017-05-09 16:33:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _get_opennebula_client(self, username, password): | 
					
						
							|  |  |  |         return oca.Client("{0}:{1}".format( | 
					
						
							|  |  |  |             username, | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-09 16:33:56 +02:00
										 |  |  |             password), | 
					
						
							|  |  |  |             "{protocol}://{domain}:{port}{endpoint}".format( | 
					
						
							|  |  |  |                 protocol=settings.OPENNEBULA_PROTOCOL, | 
					
						
							|  |  |  |                 domain=settings.OPENNEBULA_DOMAIN, | 
					
						
							|  |  |  |                 port=settings.OPENNEBULA_PORT, | 
					
						
							|  |  |  |                 endpoint=settings.OPENNEBULA_ENDPOINT | 
					
						
							| 
									
										
										
										
											2017-07-26 19:41:05 +02:00
										 |  |  |             )) | 
					
						
							| 
									
										
										
										
											2017-05-09 16:33:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  |     def _get_user(self, user): | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |         """Get the corresponding opennebula user for a CustomUser object
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  |         Args: | 
					
						
							|  |  |  |             user (CustomUser): dynamicweb CustomUser object | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Returns: | 
					
						
							|  |  |  |             oca.User: Opennebula user object | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Raise: | 
					
						
							|  |  |  |             WrongNameError: If no openebula user with this credentials exists | 
					
						
							|  |  |  |             ConnectionError: If the connection to the opennebula server can't be | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |                 established | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         user_pool = self._get_user_pool() | 
					
						
							|  |  |  |         return user_pool.get_by_name(user.email) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_user(self, user: CustomUser): | 
					
						
							|  |  |  |         """Create a new opennebula user or a corresponding CustomUser object
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  |         Args: | 
					
						
							|  |  |  |             user (CustomUser): dynamicweb CustomUser object | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Returns: | 
					
						
							|  |  |  |             int: Return the opennebula user id | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  |         Raises: | 
					
						
							|  |  |  |             ConnectionError: If the connection to the opennebula server can't be | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |                 established | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  |             UserExistsError: If a user with this credeintals already exits on the | 
					
						
							|  |  |  |                 server | 
					
						
							|  |  |  |             UserCredentialError: If a user with this email exists but the | 
					
						
							|  |  |  |                 password is worng | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             self._get_user(user) | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |             try: | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  |                 self._get_client(self, user) | 
					
						
							|  |  |  |                 logger.debug('User already exists') | 
					
						
							|  |  |  |                 raise UserExistsError() | 
					
						
							|  |  |  |             except OpenNebulaException as err: | 
					
						
							|  |  |  |                 logger.error('OpenNebulaException error: {0}'.format(err)) | 
					
						
							|  |  |  |                 logger.debug('User exists but password is wrong') | 
					
						
							|  |  |  |                 raise UserCredentialError() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         except WrongNameError: | 
					
						
							|  |  |  |             user_id = self.oneadmin_client.call(oca.User.METHODS['allocate'], | 
					
						
							| 
									
										
										
										
											2017-08-29 18:02:56 +02:00
										 |  |  |                                                 user.email, user.password, | 
					
						
							|  |  |  |                                                 'core') | 
					
						
							|  |  |  |             logger.debug( | 
					
						
							|  |  |  |                 'Created a user for CustomObject: {user} with user id = {u_id}', | 
					
						
							|  |  |  |                 user=user, | 
					
						
							|  |  |  |                 u_id=user_id | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |             return user_id | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  |         except ConnectionRefusedError: | 
					
						
							| 
									
										
										
										
											2017-08-29 18:02:56 +02:00
										 |  |  |             logger.error( | 
					
						
							|  |  |  |                 'Could not connect to host: {host} via protocol {protocol}'.format( | 
					
						
							|  |  |  |                     host=settings.OPENNEBULA_DOMAIN, | 
					
						
							|  |  |  |                     protocol=settings.OPENNEBULA_PROTOCOL) | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  |             ) | 
					
						
							|  |  |  |             raise ConnectionRefusedError | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-09 16:33:56 +02:00
										 |  |  |     def _get_or_create_user(self, email, password): | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2017-05-10 00:39:41 +02:00
										 |  |  |             user_pool = self._get_user_pool() | 
					
						
							| 
									
										
										
										
											2017-05-09 16:33:56 +02:00
										 |  |  |             opennebula_user = user_pool.get_by_name(email) | 
					
						
							|  |  |  |             return opennebula_user | 
					
						
							|  |  |  |         except WrongNameError as wrong_name_err: | 
					
						
							| 
									
										
										
										
											2017-08-29 18:02:56 +02:00
										 |  |  |             opennebula_user = self.oneadmin_client.call( | 
					
						
							|  |  |  |                 oca.User.METHODS['allocate'], email, | 
					
						
							|  |  |  |                 password, 'core') | 
					
						
							| 
									
										
										
										
											2017-05-13 05:50:56 +02:00
										 |  |  |             logger.debug( | 
					
						
							| 
									
										
										
										
											2017-09-24 02:03:48 +05:30
										 |  |  |                 "User {} does not exist. Created the user. User id = {}".format( | 
					
						
							| 
									
										
										
										
											2017-09-28 04:57:40 +05:30
										 |  |  |                     email, | 
					
						
							|  |  |  |                     opennebula_user | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2017-05-10 02:49:03 +02:00
										 |  |  |             return opennebula_user | 
					
						
							| 
									
										
										
										
											2017-05-10 00:39:41 +02:00
										 |  |  |         except ConnectionRefusedError: | 
					
						
							| 
									
										
										
										
											2017-08-29 18:02:56 +02:00
										 |  |  |             logger.info( | 
					
						
							|  |  |  |                 'Could not connect to host: {host} via protocol {protocol}'.format( | 
					
						
							|  |  |  |                     host=settings.OPENNEBULA_DOMAIN, | 
					
						
							|  |  |  |                     protocol=settings.OPENNEBULA_PROTOCOL) | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  |             ) | 
					
						
							| 
									
										
										
										
											2017-05-11 04:05:58 +02:00
										 |  |  |             raise ConnectionRefusedError | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-09 17:15:12 +02:00
										 |  |  |     def _get_user_pool(self): | 
					
						
							| 
									
										
										
										
											2017-05-10 00:39:41 +02:00
										 |  |  |         try: | 
					
						
							|  |  |  |             user_pool = oca.UserPool(self.oneadmin_client) | 
					
						
							|  |  |  |             user_pool.info() | 
					
						
							|  |  |  |         except ConnectionRefusedError: | 
					
						
							| 
									
										
										
										
											2017-08-29 18:02:56 +02:00
										 |  |  |             logger.info( | 
					
						
							|  |  |  |                 'Could not connect to host: {host} via protocol {protocol}'.format( | 
					
						
							|  |  |  |                     host=settings.OPENNEBULA_DOMAIN, | 
					
						
							|  |  |  |                     protocol=settings.OPENNEBULA_PROTOCOL) | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  |             ) | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |             raise | 
					
						
							| 
									
										
										
										
											2017-05-09 17:15:12 +02:00
										 |  |  |         return user_pool | 
					
						
							| 
									
										
										
										
											2017-05-10 01:31:27 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-11 04:05:58 +02:00
										 |  |  |     def _get_vm_pool(self): | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2017-05-11 12:45:09 +02:00
										 |  |  |             vm_pool = oca.VirtualMachinePool(self.client) | 
					
						
							|  |  |  |             vm_pool.info() | 
					
						
							| 
									
										
										
										
											2017-05-21 22:01:26 -05:00
										 |  |  |             return vm_pool | 
					
						
							| 
									
										
										
										
											2017-05-11 12:45:09 +02:00
										 |  |  |         except AttributeError: | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  |             logger.info('Could not connect via client, using oneadmin instead') | 
					
						
							| 
									
										
										
										
											2017-05-14 12:44:36 +02:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 vm_pool = oca.VirtualMachinePool(self.oneadmin_client) | 
					
						
							|  |  |  |                 vm_pool.info(filter=-2) | 
					
						
							| 
									
										
										
										
											2017-05-14 12:45:22 +02:00
										 |  |  |                 return vm_pool | 
					
						
							| 
									
										
										
										
											2017-05-14 12:44:36 +02:00
										 |  |  |             except: | 
					
						
							|  |  |  |                 raise ConnectionRefusedError | 
					
						
							| 
									
										
										
										
											2017-05-11 12:45:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-11 04:05:58 +02:00
										 |  |  |         except ConnectionRefusedError: | 
					
						
							| 
									
										
										
										
											2017-08-29 18:02:56 +02:00
										 |  |  |             logger.info( | 
					
						
							|  |  |  |                 'Could not connect to host: {host} via protocol {protocol}'.format( | 
					
						
							|  |  |  |                     host=settings.OPENNEBULA_DOMAIN, | 
					
						
							|  |  |  |                     protocol=settings.OPENNEBULA_PROTOCOL) | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  |             ) | 
					
						
							| 
									
										
										
										
											2017-05-11 04:05:58 +02:00
										 |  |  |             raise ConnectionRefusedError | 
					
						
							| 
									
										
										
										
											2017-05-14 12:22:10 +02:00
										 |  |  |         # For now we'll just handle all other errors as connection errors | 
					
						
							|  |  |  |         except: | 
					
						
							|  |  |  |             raise ConnectionRefusedError | 
					
						
							| 
									
										
										
										
											2017-05-11 04:05:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-12 12:07:05 +02:00
										 |  |  |     def get_vms(self): | 
					
						
							| 
									
										
										
										
											2017-05-13 05:50:56 +02:00
										 |  |  |         try: | 
					
						
							|  |  |  |             return self._get_vm_pool() | 
					
						
							|  |  |  |         except ConnectionRefusedError: | 
					
						
							| 
									
										
										
										
											2017-05-14 12:22:10 +02:00
										 |  |  |             raise ConnectionRefusedError | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-12 12:07:05 +02:00
										 |  |  |     def get_vm(self, vm_id): | 
					
						
							| 
									
										
										
										
											2017-05-13 06:59:57 +02:00
										 |  |  |         vm_id = int(vm_id) | 
					
						
							| 
									
										
										
										
											2017-05-13 05:50:56 +02:00
										 |  |  |         try: | 
					
						
							|  |  |  |             vm_pool = self._get_vm_pool() | 
					
						
							| 
									
										
										
										
											2017-05-13 06:59:57 +02:00
										 |  |  |             return vm_pool.get_by_id(vm_id) | 
					
						
							| 
									
										
										
										
											2017-06-15 07:30:47 +05:30
										 |  |  |         except WrongIdError: | 
					
						
							|  |  |  |             raise WrongIdError | 
					
						
							| 
									
										
										
										
											2017-05-13 05:50:56 +02:00
										 |  |  |         except: | 
					
						
							| 
									
										
										
										
											2017-05-14 12:22:10 +02:00
										 |  |  |             raise ConnectionRefusedError | 
					
						
							| 
									
										
										
										
											2017-05-10 01:31:27 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-31 18:33:07 +02:00
										 |  |  |     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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-29 19:23:25 +03:00
										 |  |  |     def create_vm(self, template_id, specs, ssh_key=None, vm_name=None): | 
					
						
							| 
									
										
										
										
											2017-05-13 06:59:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-13 13:47:53 +02:00
										 |  |  |         template = self.get_template(template_id) | 
					
						
							|  |  |  |         vm_specs_formatter = """<TEMPLATE>
 | 
					
						
							|  |  |  |                                  <MEMORY>{memory}</MEMORY> | 
					
						
							|  |  |  |                                  <VCPU>{vcpu}</VCPU> | 
					
						
							|  |  |  |                                  <CPU>{cpu}</CPU> | 
					
						
							| 
									
										
										
										
											2017-05-24 20:45:20 +02:00
										 |  |  |                              """
 | 
					
						
							| 
									
										
										
										
											2017-05-14 02:18:16 +02:00
										 |  |  |         try: | 
					
						
							|  |  |  |             disk = template.template.disks[0] | 
					
						
							|  |  |  |             image_id = disk.image_id | 
					
						
							|  |  |  |             vm_specs = vm_specs_formatter.format( | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  |                 vcpu=int(specs['cpu']), | 
					
						
							|  |  |  |                 cpu=0.1 * int(specs['cpu']), | 
					
						
							|  |  |  |                 memory=1024 * int(specs['memory']), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2017-05-14 02:18:16 +02:00
										 |  |  |             vm_specs += """<DISK>
 | 
					
						
							|  |  |  |                                   <TYPE>fs</TYPE> | 
					
						
							|  |  |  |                                   <SIZE>{size}</SIZE> | 
					
						
							|  |  |  |                                   <DEV_PREFIX>vd</DEV_PREFIX> | 
					
						
							|  |  |  |                                   <IMAGE_ID>{image_id}</IMAGE_ID> | 
					
						
							|  |  |  |                            </DISK> | 
					
						
							|  |  |  |                         """.format(size=1024 * int(specs['disk_size']),
 | 
					
						
							|  |  |  |                                    image_id=image_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         except: | 
					
						
							|  |  |  |             disk = template.template.disks[0] | 
					
						
							|  |  |  |             image = disk.image | 
					
						
							|  |  |  |             image_uname = disk.image_uname | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             vm_specs = vm_specs_formatter.format( | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  |                 vcpu=int(specs['cpu']), | 
					
						
							|  |  |  |                 cpu=0.1 * int(specs['cpu']), | 
					
						
							|  |  |  |                 memory=1024 * int(specs['memory']), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2017-05-14 02:18:16 +02:00
										 |  |  |             vm_specs += """<DISK>
 | 
					
						
							|  |  |  |                                   <TYPE>fs</TYPE> | 
					
						
							|  |  |  |                                   <SIZE>{size}</SIZE> | 
					
						
							|  |  |  |                                   <DEV_PREFIX>vd</DEV_PREFIX> | 
					
						
							|  |  |  |                                   <IMAGE>{image}</IMAGE> | 
					
						
							|  |  |  |                                   <IMAGE_UNAME>{image_uname}</IMAGE_UNAME> | 
					
						
							|  |  |  |                            </DISK> | 
					
						
							|  |  |  |                         """.format(size=1024 * int(specs['disk_size']),
 | 
					
						
							|  |  |  |                                    image=image, | 
					
						
							|  |  |  |                                    image_uname=image_uname) | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-21 13:13:10 +05:30
										 |  |  |         vm_specs += "<CONTEXT>" | 
					
						
							| 
									
										
										
										
											2017-06-02 00:49:17 +02:00
										 |  |  |         if ssh_key: | 
					
						
							| 
									
										
										
										
											2017-08-29 18:02:56 +02:00
										 |  |  |             vm_specs += "<SSH_PUBLIC_KEY>{ssh}</SSH_PUBLIC_KEY>".format( | 
					
						
							|  |  |  |                 ssh=ssh_key) | 
					
						
							| 
									
										
										
										
											2017-06-21 13:13:10 +05:30
										 |  |  |         vm_specs += """<NETWORK>YES</NETWORK>
 | 
					
						
							| 
									
										
										
										
											2017-06-02 00:49:17 +02:00
										 |  |  |                    </CONTEXT> | 
					
						
							| 
									
										
										
										
											2017-06-21 13:13:10 +05:30
										 |  |  |                 </TEMPLATE> | 
					
						
							|  |  |  |                 """
 | 
					
						
							| 
									
										
										
										
											2017-05-25 00:18:03 +02:00
										 |  |  |         vm_id = self.client.call(oca.VmTemplate.METHODS['instantiate'], | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  |                                  template.id, | 
					
						
							|  |  |  |                                  '', | 
					
						
							|  |  |  |                                  True, | 
					
						
							|  |  |  |                                  vm_specs, | 
					
						
							|  |  |  |                                  False) | 
					
						
							| 
									
										
										
										
											2017-05-13 06:59:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-25 00:18:03 +02:00
										 |  |  |         self.oneadmin_client.call( | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  |             oca.VirtualMachine.METHODS['action'], | 
					
						
							|  |  |  |             'release', | 
					
						
							|  |  |  |             vm_id | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2017-06-29 19:23:25 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-22 00:17:53 +05:30
										 |  |  |         if vm_name is not None: | 
					
						
							|  |  |  |             self.oneadmin_client.call( | 
					
						
							|  |  |  |                 'vm.rename', | 
					
						
							|  |  |  |                 vm_id, | 
					
						
							|  |  |  |                 vm_name | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2017-05-10 01:31:27 +02:00
										 |  |  |         return vm_id | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-11 04:05:58 +02:00
										 |  |  |     def delete_vm(self, vm_id): | 
					
						
							| 
									
										
										
										
											2017-05-12 12:13:18 -05:00
										 |  |  |         TERMINATE_ACTION = 'terminate' | 
					
						
							|  |  |  |         vm_terminated = False | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             self.oneadmin_client.call( | 
					
						
							|  |  |  |                 oca.VirtualMachine.METHODS['action'], | 
					
						
							|  |  |  |                 TERMINATE_ACTION, | 
					
						
							|  |  |  |                 int(vm_id), | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             vm_terminated = True | 
					
						
							|  |  |  |         except socket.timeout as socket_err: | 
					
						
							|  |  |  |             logger.info("Socket timeout error: {0}".format(socket_err)) | 
					
						
							|  |  |  |         except OpenNebulaException as opennebula_err: | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  |             logger.info( | 
					
						
							|  |  |  |                 "OpenNebulaException error: {0}".format(opennebula_err)) | 
					
						
							| 
									
										
										
										
											2017-05-12 12:13:18 -05:00
										 |  |  |         except OSError as os_err: | 
					
						
							|  |  |  |             logger.info("OSError : {0}".format(os_err)) | 
					
						
							|  |  |  |         except ValueError as value_err: | 
					
						
							|  |  |  |             logger.info("ValueError : {0}".format(value_err)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return vm_terminated | 
					
						
							| 
									
										
										
										
											2017-05-11 04:05:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _get_template_pool(self): | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  |             template_pool = oca.VmTemplatePool(self.oneadmin_client) | 
					
						
							|  |  |  |             template_pool.info() | 
					
						
							|  |  |  |             return template_pool | 
					
						
							| 
									
										
										
										
											2017-05-11 04:05:58 +02:00
										 |  |  |         except ConnectionRefusedError: | 
					
						
							| 
									
										
										
										
											2017-08-29 18:02:56 +02:00
										 |  |  |             logger.info( | 
					
						
							| 
									
										
										
										
											2017-09-14 15:27:25 +02:00
										 |  |  |                 """Could not connect to host: {host} via protocol
 | 
					
						
							|  |  |  |                  {protocol}""".format(
 | 
					
						
							| 
									
										
										
										
											2017-08-29 18:02:56 +02:00
										 |  |  |                     host=settings.OPENNEBULA_DOMAIN, | 
					
						
							|  |  |  |                     protocol=settings.OPENNEBULA_PROTOCOL) | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  |             ) | 
					
						
							| 
									
										
										
										
											2017-05-11 04:05:58 +02:00
										 |  |  |             raise ConnectionRefusedError | 
					
						
							| 
									
										
										
										
											2017-05-14 12:22:10 +02:00
										 |  |  |         except: | 
					
						
							|  |  |  |             raise ConnectionRefusedError | 
					
						
							| 
									
										
										
										
											2017-05-11 04:05:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-12 12:07:05 +02:00
										 |  |  |     def get_templates(self): | 
					
						
							| 
									
										
										
										
											2017-05-13 05:50:56 +02:00
										 |  |  |         try: | 
					
						
							|  |  |  |             public_templates = [ | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  |                 template | 
					
						
							|  |  |  |                 for template in self._get_template_pool() | 
					
						
							| 
									
										
										
										
											2017-07-26 19:41:05 +02:00
										 |  |  |                 if template.name.startswith('public-') | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  |             ] | 
					
						
							|  |  |  |             return public_templates | 
					
						
							| 
									
										
										
										
											2017-05-13 05:50:56 +02:00
										 |  |  |         except ConnectionRefusedError: | 
					
						
							| 
									
										
										
										
											2017-05-14 12:22:10 +02:00
										 |  |  |             raise ConnectionRefusedError | 
					
						
							|  |  |  |         except: | 
					
						
							|  |  |  |             raise ConnectionRefusedError | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def try_get_templates(self): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             return self.get_templates() | 
					
						
							|  |  |  |         except: | 
					
						
							| 
									
										
										
										
											2017-05-13 05:50:56 +02:00
										 |  |  |             return [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-12 12:07:05 +02:00
										 |  |  |     def get_template(self, template_id): | 
					
						
							| 
									
										
										
										
											2017-05-13 06:59:57 +02:00
										 |  |  |         template_id = int(template_id) | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             template_pool = self._get_template_pool() | 
					
						
							|  |  |  |             return template_pool.get_by_id(template_id) | 
					
						
							|  |  |  |         except: | 
					
						
							| 
									
										
										
										
											2017-05-14 12:22:10 +02:00
										 |  |  |             raise ConnectionRefusedError | 
					
						
							| 
									
										
										
										
											2017-05-11 04:05:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-29 18:02:56 +02:00
										 |  |  |     def create_template(self, name, cores, memory, disk_size, core_price, | 
					
						
							|  |  |  |                         memory_price, | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  |                         disk_size_price, ssh=''): | 
					
						
							| 
									
										
										
										
											2017-05-10 02:49:03 +02:00
										 |  |  |         """Create and add a new template to opennebula.
 | 
					
						
							|  |  |  |         :param name:      A string representation describing the template. | 
					
						
							|  |  |  |                           Used as label in view. | 
					
						
							|  |  |  |         :param cores:     Amount of virtual cpu cores for the VM. | 
					
						
							| 
									
										
										
										
											2017-05-12 12:07:05 +02:00
										 |  |  |         :param memory:  Amount of RAM for the VM (GB) | 
					
						
							|  |  |  |         :param disk_size:    Amount of disk space for VM (GB) | 
					
						
							|  |  |  |         :param core_price:     Price of virtual cpu for the VM per core. | 
					
						
							|  |  |  |         :param memory_price:  Price of RAM for the VM per GB | 
					
						
							|  |  |  |         :param disk_size_price:    Price of disk space for VM per GB | 
					
						
							|  |  |  |         :param ssh: User public ssh key | 
					
						
							| 
									
										
										
										
											2017-05-10 02:49:03 +02:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2017-05-10 01:11:49 +02:00
										 |  |  |         template_string_formatter = """<TEMPLATE>
 | 
					
						
							|  |  |  |                                         <NAME>{name}</NAME> | 
					
						
							|  |  |  |                                         <MEMORY>{memory}</MEMORY> | 
					
						
							|  |  |  |                                         <VCPU>{vcpu}</VCPU> | 
					
						
							|  |  |  |                                         <CPU>{cpu}</CPU> | 
					
						
							|  |  |  |                                         <DISK> | 
					
						
							|  |  |  |                                          <TYPE>fs</TYPE> | 
					
						
							|  |  |  |                                          <SIZE>{size}</SIZE> | 
					
						
							|  |  |  |                                          <DEV_PREFIX>vd</DEV_PREFIX> | 
					
						
							|  |  |  |                                         </DISK> | 
					
						
							| 
									
										
										
										
											2017-05-12 12:07:05 +02:00
										 |  |  |                                         <CPU_COST>{cpu_cost}</CPU_COST> | 
					
						
							|  |  |  |                                         <MEMORY_COST>{memory_cost}</MEMORY_COST> | 
					
						
							|  |  |  |                                         <DISK_COST>{disk_cost}</DISK_COST> | 
					
						
							|  |  |  |                                         <SSH_PUBLIC_KEY>{ssh}</SSH_PUBLIC_KEY> | 
					
						
							| 
									
										
										
										
											2017-05-10 01:11:49 +02:00
										 |  |  |                                        </TEMPLATE> | 
					
						
							|  |  |  |                                        """
 | 
					
						
							|  |  |  |         template_id = oca.VmTemplate.allocate( | 
					
						
							|  |  |  |             self.oneadmin_client, | 
					
						
							|  |  |  |             template_string_formatter.format( | 
					
						
							|  |  |  |                 name=name, | 
					
						
							|  |  |  |                 vcpu=cores, | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  |                 cpu=0.1 * cores, | 
					
						
							| 
									
										
										
										
											2017-05-10 01:11:49 +02:00
										 |  |  |                 size=1024 * disk_size, | 
					
						
							| 
									
										
										
										
											2017-05-12 12:07:05 +02:00
										 |  |  |                 memory=1024 * memory, | 
					
						
							|  |  |  |                 # * 10 because we set cpu to *0.1 | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  |                 cpu_cost=10 * core_price, | 
					
						
							| 
									
										
										
										
											2017-05-12 12:07:05 +02:00
										 |  |  |                 memory_cost=memory_price, | 
					
						
							|  |  |  |                 disk_cost=disk_size_price, | 
					
						
							|  |  |  |                 ssh=ssh | 
					
						
							| 
									
										
										
										
											2017-05-10 01:11:49 +02:00
										 |  |  |             ) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return template_id | 
					
						
							| 
									
										
										
										
											2017-05-11 04:05:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def delete_template(self, template_id): | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  |         self.oneadmin_client.call(oca.VmTemplate.METHODS[ | 
					
						
							| 
									
										
										
										
											2017-07-26 19:41:05 +02:00
										 |  |  |                                       'delete'], template_id, False) | 
					
						
							| 
									
										
										
										
											2017-05-11 04:05:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-25 09:35:18 +02:00
										 |  |  |     def change_user_password(self, passwd_hash): | 
					
						
							| 
									
										
										
										
											2017-05-13 05:50:56 +02:00
										 |  |  |         self.oneadmin_client.call( | 
					
						
							|  |  |  |             oca.User.METHODS['passwd'], | 
					
						
							|  |  |  |             self.opennebula_user.id, | 
					
						
							| 
									
										
										
										
											2017-09-25 09:35:18 +02:00
										 |  |  |             passwd_hash | 
					
						
							| 
									
										
										
										
											2017-05-25 11:27:49 +02:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-01 19:08:38 +02:00
										 |  |  |     def add_public_key(self, user, public_key='', merge=False): | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |         Args: | 
					
						
							|  |  |  |             user (CustomUser): Dynamicweb user | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  |             public_key (string): Public key to add to the user | 
					
						
							| 
									
										
										
										
											2017-06-01 20:47:11 +02:00
										 |  |  |             merge (bool): Optional if True the new public key replaces the old | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         Raises: | 
					
						
							|  |  |  |             KeyExistsError: If replace is False and the user already has a | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |                 public key | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  |             WrongNameError: If no openebula user with this credentials exists | 
					
						
							|  |  |  |             ConnectionError: If the connection to the opennebula server can't be | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |                 established | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         Returns: | 
					
						
							|  |  |  |             True if public_key was added | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         # TODO: Check if we can remove this first try because we basically just | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |         # raise the possible Errors | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  |         try: | 
					
						
							|  |  |  |             open_user = self._get_user(user) | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |                 old_key = open_user.template.ssh_public_key | 
					
						
							| 
									
										
										
										
											2017-06-01 19:08:38 +02:00
										 |  |  |                 if not merge: | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  |                     raise KeyExistsError() | 
					
						
							| 
									
										
										
										
											2017-06-01 19:08:38 +02:00
										 |  |  |                 public_key += '\n{key}'.format(key=old_key) | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             except AttributeError: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |             self.oneadmin_client.call('user.update', open_user.id, | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |                                       '<CONTEXT><SSH_PUBLIC_KEY>{key}</SSH_PUBLIC_KEY></CONTEXT>' | 
					
						
							|  |  |  |                                       .format(key=public_key)) | 
					
						
							| 
									
										
										
										
											2017-05-31 18:01:54 +02:00
										 |  |  |             return True | 
					
						
							|  |  |  |         except WrongNameError: | 
					
						
							|  |  |  |             raise | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         except ConnectionError: | 
					
						
							|  |  |  |             raise | 
					
						
							| 
									
										
										
										
											2017-06-01 22:25:10 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def remove_public_key(self, user, public_key=''): | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2017-06-01 22:25:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |         Args: | 
					
						
							|  |  |  |             user (CustomUser): Dynamicweb user | 
					
						
							| 
									
										
										
										
											2017-06-01 22:25:10 +02:00
										 |  |  |             public_key (string): Public key to be removed to the user | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Raises: | 
					
						
							|  |  |  |             KeyDoesNotExistsError: If replace is False and the user already has a | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |                 public key | 
					
						
							| 
									
										
										
										
											2017-06-01 22:25:10 +02:00
										 |  |  |             WrongNameError: If no openebula user with this credentials exists | 
					
						
							|  |  |  |             ConnectionError: If the connection to the opennebula server can't be | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |                 established | 
					
						
							| 
									
										
										
										
											2017-06-01 22:25:10 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         Returns: | 
					
						
							|  |  |  |             True if public_key was removed | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             open_user = self._get_user(user) | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |                 old_key = open_user.template.ssh_public_key | 
					
						
							| 
									
										
										
										
											2017-06-01 22:25:10 +02:00
										 |  |  |                 if public_key not in old_key: | 
					
						
							| 
									
										
										
										
											2017-06-11 11:44:14 -05:00
										 |  |  |                     return False | 
					
						
							|  |  |  |                     # raise KeyDoesNotExistsError() | 
					
						
							| 
									
										
										
										
											2017-06-01 22:25:10 +02:00
										 |  |  |                 if '\n{}'.format(public_key) in old_key: | 
					
						
							|  |  |  |                     public_key = old_key.replace('\n{}'.format(public_key), '') | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |                 else: | 
					
						
							| 
									
										
										
										
											2017-06-01 22:25:10 +02:00
										 |  |  |                     public_key = old_key.replace(public_key, '') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             except AttributeError: | 
					
						
							| 
									
										
										
										
											2017-06-11 12:59:57 -05:00
										 |  |  |                 return False | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |                 # raise KeyDoesNotExistsError() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-01 22:25:10 +02:00
										 |  |  |             self.oneadmin_client.call('user.update', open_user.id, | 
					
						
							| 
									
										
										
										
											2017-06-29 17:34:40 +03:00
										 |  |  |                                       '<CONTEXT><SSH_PUBLIC_KEY>{key}</SSH_PUBLIC_KEY></CONTEXT>' | 
					
						
							|  |  |  |                                       .format(key=public_key)) | 
					
						
							| 
									
										
										
										
											2017-06-01 22:25:10 +02:00
										 |  |  |             return True | 
					
						
							|  |  |  |         except WrongNameError: | 
					
						
							|  |  |  |             raise | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         except ConnectionError: | 
					
						
							|  |  |  |             raise | 
					
						
							| 
									
										
										
										
											2017-08-29 18:02:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-31 18:33:07 +02:00
										 |  |  |     def manage_public_key(self, keys, hosts=None, countdown=0): | 
					
						
							| 
									
										
										
										
											2017-08-29 18:02:56 +02:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2017-08-31 18:33:07 +02:00
										 |  |  |         A function that manages the supplied keys in the | 
					
						
							|  |  |  |         authorized_keys file of the given list of hosts. If hosts | 
					
						
							|  |  |  |         parameter is not supplied, all hosts of this customer | 
					
						
							|  |  |  |         will be configured with the supplied keys | 
					
						
							| 
									
										
										
										
											2017-08-30 09:43:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-31 18:33:07 +02:00
										 |  |  |         :param keys: A list of ssh keys that are to be added/removed | 
					
						
							| 
									
										
										
										
											2017-08-30 09:43:54 +02:00
										 |  |  |                      A key should be a dict of the form | 
					
						
							|  |  |  |                      { | 
					
						
							|  |  |  |                        'value': 'sha-.....', # public key as string | 
					
						
							|  |  |  |                        'state': True         # whether key is to be added or | 
					
						
							|  |  |  |                      }                       # removed | 
					
						
							| 
									
										
										
										
											2017-08-31 18:33:07 +02:00
										 |  |  |         :param hosts: A list of hosts IP addresses | 
					
						
							|  |  |  |         :param countdown: Parameter to be passed to celery apply_async | 
					
						
							|  |  |  |                Allows to delay a task by `countdown` number of seconds | 
					
						
							| 
									
										
										
										
											2017-08-29 18:02:56 +02:00
										 |  |  |         :return: | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2017-08-31 18:33:07 +02:00
										 |  |  |         if hosts is None: | 
					
						
							|  |  |  |             hosts = self.get_all_hosts() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if len(hosts) > 0 and len(keys) > 0: | 
					
						
							| 
									
										
										
										
											2017-09-01 02:33:31 +05:30
										 |  |  |             save_ssh_key.apply_async((hosts, keys), countdown=countdown, | 
					
						
							|  |  |  |                                      link_error=save_ssh_key_error_handler.s()) | 
					
						
							| 
									
										
										
										
											2017-08-31 18:33:07 +02:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2017-09-13 12:24:08 +02:00
										 |  |  |             logger.debug( | 
					
						
							|  |  |  |                 "Keys and/or hosts are empty, so not managing any keys") | 
					
						
							| 
									
										
										
										
											2017-08-31 18:33:07 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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 | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2017-08-29 18:02:56 +02:00
										 |  |  |         owner = CustomUser.objects.filter( | 
					
						
							| 
									
										
										
										
											2017-08-31 12:54:08 +05:30
										 |  |  |             email=self.email).first() | 
					
						
							| 
									
										
										
										
											2017-08-29 18:02:56 +02:00
										 |  |  |         all_orders = HostingOrder.objects.filter(customer__user=owner) | 
					
						
							| 
									
										
										
										
											2017-08-31 18:33:07 +02:00
										 |  |  |         hosts = [] | 
					
						
							| 
									
										
										
										
											2017-08-29 18:02:56 +02:00
										 |  |  |         if len(all_orders) > 0: | 
					
						
							|  |  |  |             logger.debug("The user {} has 1 or more VMs. We need to configure " | 
					
						
							| 
									
										
										
										
											2017-08-31 12:54:08 +05:30
										 |  |  |                          "the ssh keys.".format(self.email)) | 
					
						
							| 
									
										
										
										
											2017-08-29 18:02:56 +02:00
										 |  |  |             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) | 
					
						
							|  |  |  |                 except WrongIdError: | 
					
						
							|  |  |  |                     logger.debug( | 
					
						
							|  |  |  |                         "VM with ID {} does not exist".format(order.vm_id)) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             logger.debug("The user {} has no VMs. We don't need to configure " | 
					
						
							| 
									
										
										
										
											2017-08-31 12:54:08 +05:30
										 |  |  |                          "the ssh keys.".format(self.email)) | 
					
						
							| 
									
										
										
										
											2017-08-31 18:33:07 +02:00
										 |  |  |         return hosts |