Пример #1
0
    def run_machine(self, machine_name, preset=False):
        if isinstance(machine_name, libvirt.virDomain): # Processing domain object itself
            try:
                self.machine_name.create()
            except Exception as e:
                error =  'Unknown error while trying to start machine by domain object: %s' % e
                print (error)
                return (False, error)
            else:
                self._prepare_database()
                return (True, 'Machine started')

        # Simple approach -> start by reading configuration file
        folder = self.PRESETS if preset else self.IMAGES
        path = safe_join(folder, machine_name)
        try:
            with open(safe_join(path, self.CONFIG_NAME)) as f:
                f = f.read()
        except IOError:
            return (False, 'Cannot open config name for %s machine' % machine_name)
        machines = self._get_online_machines()
        try:
            self.connection.createXML(f, 0)
        except libvirt.libvirtError as e:
            return (False, str(e))
        except Exception:
            return (False, 'Cannot run machine, but config file was found')
        else:
            # TODO: improve this algorithm
            cnt = 0
            while machines == self._get_online_machines() and cnt < 5:
                cnt += 1
                sleep(2)
            self._prepare_database()
            return (True, 'Machine started')
Пример #2
0
    def _get_xml_info(self, machine_name, presets=False):
        source = self.IMAGES if not presets else self.PRESETS
        path = safe_join(source, machine_name)
        # Maybe this code is too indian-styled
        try:
            with open(safe_join(path, self.CONFIG_NAME)) as f:

                dom = minidom.parse(f)
        except IOError:
            type = 'unknown'
            memory = -1
            cpu = '?'
        else:
            cpu = dom.getElementsByTagName('vcpu')[0].childNodes[0].data
            type = dom.getElementsByTagName('ajptype')[0].childNodes[0].data
            memory = int(dom.getElementsByTagName('memory')[0].
                         childNodes[0].data)/1024 # In MB
        finally:
            if not type:
                type = 'not specified'
            if not memory:
                memory = 0
            if not cpu:
                cpu = '?'
        return (type, cpu, memory)
Пример #3
0
    def get_presets_list(self):
        presets = []
        try:
            presets_list = self.db.lrange("presets", 0, -1)
        except Exception:
            pass
        else:
            if presets_list:
                for element in presets_list:
                    try:
                        element = json.loads(element)
                    except ValueError:
                        continue
                    else:
                        presets.append(element)
                print ('Cached presets: %s' % presets)
                return presets

        # If not cache
        for directory in os.listdir(self.PRESETS):
            path = safe_join(self.PRESETS, directory)
            try:
                with open(safe_join(path, self.CONFIG_NAME)) as f:
                    dom = minidom.parse(f)
                #import pdb; pdb.set_trace()
            except IOError:
                continue
            else:
                name = dom.getElementsByTagName('name')[0].childNodes[0].data # Get name of the VM
                try:
                    with open(safe_join(path, self.DESCRIPTION_NAME)) as f:
                        description = f.read()
                except IOError:
                    continue
                else:
                    presets.append({'name': name, 'description': description})


        if presets:
            for preset in presets:
                item = json.dumps(preset)
                self.db.rpush('presets', item)
        else:
            self.db.rpush('presets', 'Empty')

        self.db.expire('presets', 600)
        print ('presets: ' + str(presets))
        return presets
Пример #4
0
    def _prepare_database(self, soft=False): # aka drop cache
        # Set flags in DB and also prepare list of preset domains
        print ('Cache dropped')
        if not soft:
            self.db.expire('copy', 0)
            self.db.set('provider', 'kvm')

        self.KVM_PATH = self.pg.KVM_PATH
        self.PRESETS = safe_join(self.KVM_PATH, self.pg.PRESETS)
        self.IMAGES = safe_join(self.KVM_PATH, self.pg.IMAGES)

        self.CONFIG_NAME = self.pg.CONFIG_NAME
        self.VMIMAGE_NAME = self.pg.VMIMAGE_NAME
        self.DESCRIPTION_NAME = self.pg.DESCRIPTION_NAME

        self.VMMANAGER_PATH = self.pg.VMMANAGER_PATH

        # Cleaning cache lists
        self.db.expire('online', 0)
        self.db.expire('offline', 0)
        self.db.expire('presets', 0)
Пример #5
0
    def get_storage_info(self, machine):
        """ Calculating storage info (total, free, used) for new VM:
        We are getting all storage info and then calculate how much space
         you need to copy selected VM.

        FIXME: we are calculating info only for presets, this should be fixed for cloning
            non-preset machines.
        """
        provider = self.db.io.get('provider')
        # TODO: optimize next, or maybe move it to VM provider.
        if provider == 'kvm':
            root = self.pg.KVM_PATH
        elif provider == 'xen':
            root = self.pg.XEN_PATH
        else:
            raise NotImplementedError

        path = safe_join(root, self.pg.IMAGES)
        preset_path = safe_join(root, self.pg.PRESETS)

        total, used, free = get_storage_info(path)
        preset_storage = calculate_flat_folder_size(safe_join(preset_path, machine))
        return (total, used, free, preset_storage)
Пример #6
0
    def _define_machines(self):
        """ Adding VM into Libvirt. Also refreshing changed config files.
        """
        # Clearing all defined domains:
        #online = self._get_online_machines() # We cannot undefine running domain. So ignoring.
        offline = self._get_offline_machines()
        map(lambda x: x.undefine(), map(self.connection.lookupByName, offline))


        # Find preset's name & image name of the machine and add it into libvirt
        for category in [self.IMAGES, self.PRESETS]: # Scanning both images and presets
            for directory in os.listdir(category):
                directory_ = safe_join(category, directory)                          # Building full path
                if not os.path.isdir(directory_):
                    continue
                try:
                    with open(safe_join(directory_, self.CONFIG_NAME)) as f:
                        f = f.read()
                    self.connection.defineXML(f)
                    # vice versa -> undefine_XML
                except Exception as e:
                    print (e)
                    continue
Пример #7
0
    def _clone(self, id, preset_name, machine_name, session, force=False):
        print ('cloning')
        if self.db.get('copy'):
            print ('Copy operation in progress')
            return {'answer': False, 'message': 'Copy operation already in progress'}
        self.db.set('copy', session)

        # Path preparations
        src = safe_join(self.PRESETS, preset_name)
        dst = safe_join(self.IMAGES, machine_name)

        if not os.path.exists(dst):
            os.makedirs(dst)
        else:
            if not force and os.path.\
                exists(self.CONFIG_NAME) or os.path.\
                exists(self.VMIMAGE_NAME) or os.path.\
                exists(self.DESCRIPTION_NAME):
                return {'answer': False, 'message': 'Folder exists, use force to rewrite content'}



        # Prepare XML file
        additional_images = [] # File images (as additional partition files)
        with open(safe_join(src, self.CONFIG_NAME)) as f:
            # Now we are updating info in memory copy of preset's config file
            dom = minidom.parse(f)

            # <TOTAL_MADNESS>
            dom.getElementsByTagName('name')[0].childNodes[0].data = machine_name
            dom.getElementsByTagName('uuid')[0].childNodes[0].data = generate_uuid()

            for num, tag in enumerate(dom.getElementsByTagName('interface')):
                if tag.attributes.get('type').value == 'network':
                    dom.getElementsByTagName('interface')[num].getElementsByTagName('mac')[0].attributes.get('address').value = generate_mac()

            # Change path of the images in config
            # Add to list of images additional disks
            for num, element in enumerate(dom.getElementsByTagName('disk')):
                if element.attributes.get('device').value == 'disk':
                    path = element.getElementsByTagName('source')[0].attributes.get('file').value
                    image_name = os.path.basename(path)
                    if image_name != 'image.img':
                        additional_images.append(image_name)
                    dom.getElementsByTagName('disk')[num].\
                        getElementsByTagName('source')[0].\
                        attributes.get('file').value = safe_join(dst, image_name)

            # Write to file
            dom.writexml(open(safe_join(dst, self.CONFIG_NAME), 'w'), encoding='utf-8')
            # </TOTAL_MADNESS>

        # XML ready
        # Finding libvirt group name

        import grp
        try:
            groupinfo = grp.getgrnam('libvirt')
            gid = groupinfo.gr_gid
        except Exception as e:
            print ('Error while trying to determine libvirt\'s group: %s' % e)
            raise

        for file in [self.DESCRIPTION_NAME, self.VMIMAGE_NAME] + additional_images:
            try:
                shutil.copy2(safe_join(src, file), dst)
            except OSError as exc: # python >2.5
                print ('Exception')
                if exc.errno == 28:
                    return {'answer': False, 'message': 'No space left on device'}
                print (exc.errno)
            else:
                os.chown(safe_join(dst, file), -1, gid) # appending libvirt permissions to files
        os.chown(dst, -1, gid) # appending libvirt group to folder


        self.db.expire('copy', 0)
        # Drop cache:
        self._prepare_database(soft=True)

        # Prepare message to client
        print ('Files copied!')
        message = 'Sucessfully copied'
        return {'answer': True, 'message': message}