Commit daaebce1 authored by Thibault VINCENT's avatar Thibault VINCENT
Browse files

moved non KVM specific methods to parent class libVirtHypervisor

parent 17972215
Loading
Loading
Loading
Loading
+0 −145
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ class KvmHypervisor(LibvirtHypervisor):
        super(KvmHypervisor, self).__init__('kvm')
        self.hv_type = 'KVM/QEMU'
    
    
    def __new__(cls, *args, **kwargs):
        '''
        .. note::
@@ -34,147 +33,3 @@ class KvmHypervisor(LibvirtHypervisor):
            cls._instance = super(KvmHypervisor, cls).__new__(cls, *args,
                                                                **kwargs)
        return cls._instance

   
    def start_vm(self, name, start_options=DEFAULT_VM_START):
        '''
        Starts the vm identified by name
        
        :param name: The name of the virtual machine
        :type nane: :class:`str`

        :param start_options: Options flags while starting vm
        :type start_options: TODO reference to constants

        '''
        for vm in self._vm_list:
            if vm.get_name() == name:
                vm.start()
                return
        raise VMError('Virtual Machine %s not found: '% name)

    def stop_vm(self, name, force=False):
        '''
        Poweroff the specifed vm with the specified options

        :param name: the name of the vm
        :type name: :class:`str`
        '''
        for vm in self._vm_list:
            if vm.get_name() == name:
                vm.force_poweroff() if force else vm.shutdown()
                return
        raise VMError('Virtual Machine %s not found: ' % name)   

    def suspend_vm(self, name):
        '''
        Suspends the specifed vm

        :param name: the name of the vm
        :type name: :class:`str`
        '''
        for vm in self._vm_list:
            if vm.get_name() == name:
                vm.suspend()
                return
        raise VMError('Virtual machine %s not found: ' % name)

    def resume_vm(self, name):
        '''
        Resumes the specifed vm

        :param name: the name of the vm
        :type name: :class:`str`
        '''
        for vm in self._vm_list:
            if vm.get_name() == name:
                vm.resume()
                return
        raise VMError('Virtual machine %s not found: ' % name)


    def local_execute(self, command):
        '''
        Excecutes the command given in command on the local host
        Returns a tuple with (stdout, stderr) from the process that has
        been executed

        ..warning:: This is a dangerous function as it gives the command given
        in paramter to a shell prompt, anything can then be executed locally

        ..warning:: If the command given is a long processing one, this may be
            a deadlock to the node be carefull !

        :param command: the command to execute with it's arguments
        :type command: :class:`str`
        '''
        #FIXME: stop using shell=true and parse arguments with shlex.split()
        p = subprocess.Popen(command, shell=True,
                            bufsize=-1,
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)
        result = p.communicate()
        return result

    def export_vm(self, name, target, port):
        '''
        Migrates the given vm (name) to (target) hypervisor which is already
        waiting for the migration

        :param name: the name of the vm
        :type name: :class:`str`
        :param target: the destination hypervisor
        :type target: :class:`str`
        :param port: the port on the destination to use for the transfer
        :type port: :class:`str`
        '''
        # We will be using subprocess to pipe the volume using dd  in a netcat 
        # connection to the destination
        # We send a hash of the volume before so that the target can checksum
        # and validate integrity.
        # This algorithm is just a proof of concept of the cold migration
        # process it is likely that it does not anticipates some problems

        buff = 1024 * 1024 * 10   #10 Mo
        path = [vm.get_disk_path() for vm in self._vm_list 
                                    if vm.get_name() == name].pop()
        dd_cmd = ['dd', 'if=%s' % path]
        
        dd_process = subprocess.Popen(dd_cmd, bufsize=-1,
                                    stdout=subprocess.PIPE)
        nc_process = subprocess.Popen(['nc', target, port],
                                    bufsize=-1,
                                    stdin=subprocess.PIPE,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
        #We send dd output to nc
        dd_out = dd_process.stdout
        nc_in = nc_process.stdin
        m = hashlib.md5()
        print 'going to pipe loop'
        try:
            read = dd_out.read(buff)
        except Exception as err:
            raise IOError('error while reading dd process output %s' % err)
        try:
            while len(read) != 0:
                print len(read)
                m.update(read)
                nc_in.write(read)
                nc_in.flush()
                read = dd_out.read(buff)
        except Exception as err:
            raise IOError('Error occured while writing to nc process %s' % err)
        nc_in.close()
        print m.hexdigest()

    def get_network_conf(self):
        raise NotImplementedError

    def get_storage_conf(self):
        raise NotImplementedError

    def get_storage_stats(self):
        raise NotImplementedError
+141 −0
Original line number Diff line number Diff line
@@ -351,6 +351,147 @@ class LibvirtHypervisor(Hypervisor):
    def get_status(self):
        raise NotImplementedError()
   
    def start_vm(self, name, start_options=DEFAULT_VM_START):
        '''
        Starts the vm identified by name
        
        :param name: The name of the virtual machine
        :type nane: :class:`str`

        :param start_options: Options flags while starting vm
        :type start_options: TODO reference to constants

        '''
        for vm in self._vm_list:
            if vm.get_name() == name:
                vm.start()
                return
        raise VMError('Virtual Machine %s not found: '% name)
    
    def stop_vm(self, name, force=False):
        '''
        Poweroff the specifed vm with the specified options

        :param name: the name of the vm
        :type name: :class:`str`
        '''
        for vm in self._vm_list:
            if vm.get_name() == name:
                vm.force_poweroff() if force else vm.shutdown()
                return
        raise VMError('Virtual Machine %s not found: ' % name)   
    
    def suspend_vm(self, name):
        '''
        Suspends the specifed vm

        :param name: the name of the vm
        :type name: :class:`str`
        '''
        for vm in self._vm_list:
            if vm.get_name() == name:
                vm.suspend()
                return
        raise VMError('Virtual machine %s not found: ' % name)
    
    def resume_vm(self, name):
        '''
        Resumes the specifed vm

        :param name: the name of the vm
        :type name: :class:`str`
        '''
        for vm in self._vm_list:
            if vm.get_name() == name:
                vm.resume()
                return
        raise VMError('Virtual machine %s not found: ' % name)
    
    def local_execute(self, command):
        '''
        Excecutes the command given in command on the local host
        Returns a tuple with (stdout, stderr) from the process that has
        been executed

        ..warning:: This is a dangerous function as it gives the command given
        in paramter to a shell prompt, anything can then be executed locally

        ..warning:: If the command given is a long processing one, this may be
            a deadlock to the node be carefull !

        :param command: the command to execute with it's arguments
        :type command: :class:`str`
        '''
        #FIXME: stop using shell=true and parse arguments with shlex.split()
        p = subprocess.Popen(command, shell=True,
                            bufsize=-1,
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)
        result = p.communicate()
        return result
    
    def export_vm(self, name, target, port):
        '''
        Migrates the given vm (name) to (target) hypervisor which is already
        waiting for the migration

        :param name: the name of the vm
        :type name: :class:`str`
        :param target: the destination hypervisor
        :type target: :class:`str`
        :param port: the port on the destination to use for the transfer
        :type port: :class:`str`
        '''
        # We will be using subprocess to pipe the volume using dd  in a netcat 
        # connection to the destination
        # We send a hash of the volume before so that the target can checksum
        # and validate integrity.
        # This algorithm is just a proof of concept of the cold migration
        # process it is likely that it does not anticipates some problems

        buff = 1024 * 1024 * 10   #10 Mo
        path = [vm.get_disk_path() for vm in self._vm_list 
                                    if vm.get_name() == name].pop()
        dd_cmd = ['dd', 'if=%s' % path]
        
        dd_process = subprocess.Popen(dd_cmd, bufsize=-1,
                                    stdout=subprocess.PIPE)
        nc_process = subprocess.Popen(['nc', target, port],
                                    bufsize=-1,
                                    stdin=subprocess.PIPE,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
        #We send dd output to nc
        dd_out = dd_process.stdout
        nc_in = nc_process.stdin
        m = hashlib.md5()
        print 'going to pipe loop'
        try:
            read = dd_out.read(buff)
        except Exception as err:
            raise IOError('error while reading dd process output %s' % err)
        try:
            while len(read) != 0:
                print len(read)
                m.update(read)
                nc_in.write(read)
                nc_in.flush()
                read = dd_out.read(buff)
        except Exception as err:
            raise IOError('Error occured while writing to nc process %s' % err)
        nc_in.close()
        print m.hexdigest()
    
    def get_network_conf(self):
        raise NotImplementedError
    
    def get_storage_conf(self):
        raise NotImplementedError
    
    def get_storage_stats(self):
        raise NotImplementedError


#TODO: finish storage class, make tests,
class LibvirtHVStorage(HVStorage):
+7 −0
Original line number Diff line number Diff line
cc-node (6) unstable; urgency=low

  * Bug fix
  * Proper release with newer init scripts

 -- Thibault VINCENT <tibal@reloaded.fr>  Mon, 27 Dec 2010 17:12:40 +0100

cc-node (5-2) unstable; urgency=low

  * Fix configuration option for HV detection