# Gerer le cas ou le mdp n'est pa valable #TODO: catch livbirt disconnection errors and handle it from kvm import * from sjrpc.utils import RpcHandler from sjrpc.utils import pure from sjrpc.core import RpcError from exceptions import VMError import logging ############ ## Constants ############ # Logging errors TAG_METHOD_ERROR = 'No method found in hypervisor to handle tag %s' TAG_NOT_FOUND_ERROR = 'Tag %s requested but unknown in node handler' # Tags to method mappings # Hypervisor HV_TAG_MAP = { 'hostname' : 'get_name', 'htype' : 'get_hv_type', 'hver' : 'get_hv_version', 'arch' : 'get_arch_type', 'cpus' : 'get_nb_cpu', 'cpu_freq' : 'get_cpu_frequency', 'status' : 'get_status', 'cpu' : 'get_cpu_percent', 'mem_used' : 'get_used_mem', 'mem_avail' : 'get_free_mem', 'mem_total': 'get_total_mem' } # Vm VM_TAG_MAP = { 'vm' : 'get_name', 'vcpus' : 'get_vcpu', 'status' : 'get_status', 'cpu' : 'get_cpu_percent', 'vmem_used' : 'get_used_mem', 'vmem_avail' : 'get_free_mem', 'vmem_total' : 'get_total_mem' } class NodeHandler(RpcHandler): ''' This is the main node handler that exports the hypervisor capabilities to any connected server. In other terms this is the node interface to the server. ''' def __init__(self, connection): super(RpcHandler, self).__init__() self._connection = connection #we set our hypervisor handle #FIXME: must be aware of hypervisor type logging.debug('Initializing a handle over the hypervisor') self.hv_handle = KvmHypervisor() def _call_hv_method(self, method): ''' Calls the given method in the :class:`Hypervisor` instance Returns the result of the method called :param method: the method to be called :type method: :class:`str` ''' result = getattr(self.hv_handle, HV_TAG_MAP[method])() return result def _call_vm_method(self, vm, method): ''' Calls the given method in vm instance Returns the result of the method called :param vm: The vm object in which call the method :vm type: :class:`VM` :param method: the method to be called :type method: :class:`str` ''' result = getattr(vm, VM_TAG_MAP[method])() return result @pure def get_tags(self, tags=None): ''' Return tags bound to hypervisor specified in tags parameter otherwise returns all :param tags: list of tags or None :type tags: :class:`list` ''' result = {} logging.debug('get_tags: Fetching tags -> %s' % tags) if tags is None: tags = HV_TAG_MAP.keys() logging.debug('get_tags: processing tags %s' % tags) for tag in tags: try: result[tag] = self._call_hv_method(tag) except AttributeError: logging.warning(TAG_METHOD_ERROR % tag) except KeyError: logging.warning(TAG_NOT_FOUND_ERROR % tag) except NotImplementedError: logging.debug('get_tags: no method in hypervisor to handle %s' % tag) logging.debug('get_tags: returning -> %s' % result) return result @pure def list_vm(self, vm_names=None, tags=None): ''' Return a list of vm tags :param vm_names: vm names :type vm_names: :class:`list` of strings :param tags: tags to be returned :type tags: :class:`list` of strings ''' vms_info = [] vm_info = {} tags = VM_TAG_MAP.keys() if tags is None else tags logging.debug('list_vm: processing tags %s' % tags) # ensure that vm name is always returned if not tags.__contains__('vm'): tags.insert(0, 'vm') logging.debug('list_vm: fetching tag list %s' % tags) for vm in self.hv_handle.get_vms(): for tag in tags: try: vm_info[tag] = self._call_vm_method(vm, tag) except AttributeError: logging.warning(TAG_METHOD_ERROR % tag) except KeyError: logging.warning(TAG_NOT_FOUND_ERROR % tag) except NotImplementedError: logging.debug('list_vm: method in vm to handle %s' % tag) vms_info.append(vm_info) vm_info = {} if vm_names: logging.debug('list_vm: filtering tag results for vms %s' % vm_names) filterd_vms = [vm for vm in vms_info if vm['vm'] in vm_names] logging.debug('list_vm: returning -> %s' % filterd_vms) return filterd_vms else: logging.debug('list_vm: returning -> %s' % vms_info) return vms_info @pure def stop_vm(self, vm_names=None, force=False): ''' Stop the specified list of vm names This method do a soft shutdown on the Virtual Machine If vm_names is None all vms in hypervisor will be stopped :param vm_names: the list of vm names to stop :vm_names type: :class:`list` of strings :param stop_mode: soft shutown or force poweroff :type stop_mode: either `FORCE_VM_POWEROFF` or `SOFT_VM_POWEROFF` default is SOFT_VM_POWEROFF ''' if vm_names is None: #fetch all vm names in hypervisor vm_names = [vm.get_name() for vm in self.hv_handle._vm_list] logging.debug('stop_vm: stopping vms %s' % vm_names) for vm in vm_names: try: self.hv_handle.stop_vm(vm, stop_mode) except VMError as err: logging.warning('Error while stopping %s: %s' % (vm, err)) else: logging.info('stop_vm: vm %s stopping' % vm) @pure def start_vm(self, vm_names=None): ''' Starts the specified list of vms If vm_names is None all vms in the hypervisor will be started :param vm_names: the list of vms to start :type vm_names: :class:`list` of strings ''' if vm_names is None: vm_names = gen_vm_names(self.hv_handle) logging.debug('start_vm: starting vms %s' % vm_names) for vm in vm_names: try: self.hv_handle.start_vm(vm) except VMError as err: logging.warning('Error while starting %s: %s' % (vm ,err)) else: logging.info('start_vm: vm %s starting' % vm) @pure def suspend_vm(self, vm_names=None): ''' Suspends the specifed list of vms If vm_names is None all vms in hypervisor will be suspended :param vm_names: the list of vms to suspend :type vm_names: :class:`list` of strings ''' if vm_names is None: vm_names = gen_vm_names(self.hv_handle) logging.debug('suspend_vm: suspending vms %s' % vm_names) for vm in vm_names: try: self.hv_handle.suspend_vm(vm) except VMError as err: logging.info('Error while suspending %s: %s' % (vm, err)) else: logging.info('suspend_vm: vm %s suspended' % vm) @pure def resume_vm(self, vm_names=None): ''' Resumes the specified list of vms If vm_names is None all vms in hypervisor will be resumed :param vm_names: the list of vms to resume :type vm_names: :class:`str` ''' if vm_names is None: vm_names = gen_vm_names(self.hv_handle) logging.debug('resume_vm: resuming vms %s' % vm_names) for vm in vm_names: try: self.hv_handle.resume_vm(vm) except VMError as err: logging.info('Error while resuming %s: %s' % (vm, err)) else: logging.info('resume_vm: vm %s resumed' % vm) @pure def execute_command(self, command): ''' Excecutes the given command on the local hypervisor :param command: the command to excecute as it would be typed on a shell prompt :type command: :class:`str` ''' result = self.hv_handle.local_excecute(command) return result ### Helper Functions def gen_vm_names(hypervisor): ''' generates a list of vm names defined in hypervisor ''' return [vm.get_name() for vm in hypervisor._vm_list]