Ejemplo n.º 1
0
    def __init__(self, **kargs):
        self.conn = kargs['conn']
        self.objstore = kargs['objstore']
        self.scanner = Scanner(self._clean_scan)
        self.scanner.delete()
        self.caps = CapabilitiesModel(**kargs)
        self.device = DeviceModel(**kargs)

        if self.conn.isQemuURI():
            self._check_default_pools()
Ejemplo n.º 2
0
class StoragePoolsModel(object):
    def __init__(self, **kargs):
        self.conn = kargs['conn']
        self.objstore = kargs['objstore']
        self.scanner = Scanner(self._clean_scan)
        self.scanner.delete()
        self.caps = CapabilitiesModel(**kargs)
        self.device = DeviceModel(**kargs)

        if self.conn.isQemuURI():
            self._check_default_pools()

    def _check_default_pools(self):
        pools = {}

        default_pool = tmpl_defaults['storagepool']
        default_pool = default_pool.split('/')[-1]

        pools[default_pool] = {}
        if default_pool == 'default':
            pools[default_pool] = {'path': '/var/lib/libvirt/images'}

        if config.get("server", "create_iso_pool") == "true":
            pools['ISO'] = {'path': '/var/lib/kimchi/isos'}

        error_msg = ("Please, check the configuration in %s/template.conf to "
                     "ensure it has a valid storage pool." %
                     PluginPaths('kimchi').conf_dir)

        conn = self.conn.get()
        for pool_name in pools:
            try:
                pool = conn.storagePoolLookupByName(pool_name)
            except libvirt.libvirtError, e:
                pool_path = pools[pool_name].get('path')
                if pool_path is None:
                    msg = "Fatal: Unable to find storage pool %s. " + error_msg
                    wok_log.error(msg % pool_name)
                    wok_log.error("Details: %s", e.message)
                    sys.exit(1)

                # Try to create the pool
                pool = E.pool(E.name(pool_name), type='dir')
                pool.append(E.target(E.path(pool_path)))
                xml = ET.tostring(pool)
                try:
                    pool = conn.storagePoolDefineXML(xml, 0)
                except libvirt.libvirtError, e:
                    msg = "Fatal: Unable to create storage pool %s. "
                    msg += error_msg
                    wok_log.error(msg % pool_name)
                    wok_log.error("Details: %s", e.message)
                    sys.exit(1)

                # Build and set autostart value to pool
                # Ignore error as the pool was already successfully created
                try:
                    # Add build step to make sure target directory created
                    # The build process may fail when the pool directory
                    # already exists on system
                    pool.build(libvirt.VIR_STORAGE_POOL_BUILD_NEW)
                    pool.setAutostart(1)
                except:
                    pass

            if pool.isActive() == 0:
                try:
                    pool.create(0)
                except libvirt.libvirtError, e:
                    msg = "Fatal: Unable to craete storage pool %s. "
                    msg += error_msg
                    wok_log.error(msg % pool_name)
                    wok_log.error("Details: %s", e.message)
                    sys.exit(1)
Ejemplo n.º 3
0
class StoragePoolsModel(object):
    def __init__(self, **kargs):
        self.conn = kargs['conn']
        self.objstore = kargs['objstore']
        self.scanner = Scanner(self._clean_scan)
        self.scanner.delete()
        self.caps = CapabilitiesModel(**kargs)
        self.device = DeviceModel(**kargs)

        if self.conn.isQemuURI():
            self._check_default_pools()

    def _check_default_pools(self):
        pools = {}

        default_pool = tmpl_defaults['disks'][0]['pool']['name']
        default_pool = default_pool.split('/')[-1]

        pools[default_pool] = {}
        if default_pool == 'default':
            pools[default_pool] = {'path': '/var/lib/libvirt/images'}

        if config.get('kimchi', {}).get('create_iso_pool', False):
            pools['ISO'] = {'path': '/var/lib/kimchi/isos'}

        error_msg = ("Please, check the configuration in %s/template.conf to "
                     "ensure it has a valid storage pool." %
                     kimchiPaths.sysconf_dir)

        conn = self.conn.get()
        for pool_name in pools:
            try:
                pool = conn.storagePoolLookupByName(pool_name)
            except libvirt.libvirtError, e:
                pool_path = pools[pool_name].get('path')
                if pool_path is None:
                    msg = "Fatal: Unable to find storage pool %s. " + error_msg
                    wok_log.error(msg % pool_name)
                    wok_log.error("Details: %s", e.message)
                    sys.exit(1)

                # Try to create the pool
                pool = E.pool(E.name(pool_name), type='dir')
                pool.append(E.target(E.path(pool_path)))
                xml = ET.tostring(pool)
                try:
                    pool = conn.storagePoolDefineXML(xml, 0)
                except libvirt.libvirtError, e:
                    msg = "Fatal: Unable to create storage pool %s. "
                    msg += error_msg
                    wok_log.error(msg % pool_name)
                    wok_log.error("Details: %s", e.message)
                    sys.exit(1)

                # Build and set autostart value to pool
                # Ignore error as the pool was already successfully created
                try:
                    # Add build step to make sure target directory created
                    # The build process may fail when the pool directory
                    # already exists on system
                    pool.build(libvirt.VIR_STORAGE_POOL_BUILD_NEW)
                    pool.setAutostart(1)
                except:
                    pass

            if pool.isActive() == 0:
                try:
                    pool.create(0)
                except libvirt.libvirtError, e:
                    msg = "Fatal: Unable to craete storage pool %s. "
                    msg += error_msg
                    wok_log.error(msg % pool_name)
                    wok_log.error("Details: %s", e.message)
                    sys.exit(1)
Ejemplo n.º 4
0
class StoragePoolsModel(object):

    def __init__(self, **kargs):
        self.conn = kargs['conn']
        self.objstore = kargs['objstore']
        self.scanner = Scanner(self._clean_scan)
        self.scanner.delete()
        self.caps = CapabilitiesModel(**kargs)
        self.device = DeviceModel(**kargs)

        if self.conn.get() is not None:
            if self.conn.isQemuURI():
                self._check_default_pools()

    def _check_default_pools(self):
        pools = {}

        # Don't create default pool if it's not
        # explicitly specified in template.conf
        if is_s390x() and 'pool' not in tmpl_defaults['disks'][0]:
            return

        default_pool = tmpl_defaults['disks'][0]['pool']['name']
        default_pool = default_pool.split('/')[-1]

        pools[default_pool] = {}
        if default_pool == 'default':
            pools[default_pool] = {'path': '/var/lib/libvirt/images'}

        if config.get('kimchi', {}).get('create_iso_pool', False):
            pools['ISO'] = {'path': '/var/lib/kimchi/isos'}

        conn = self.conn.get()
        for pool_name in pools:
            error_msg = ("Storage pool %s does not exist or is not "
                         "active. Please, check the configuration in "
                         "%s/template.conf to ensure it lists only valid "
                         "storage." % (pool_name, kimchiPaths.sysconf_dir))
            try:
                pool = conn.storagePoolLookupByName(pool_name)
            except libvirt.libvirtError, e:
                pool_path = pools[pool_name].get('path')
                if pool_path is None:
                    msg = "Fatal: Unable to find storage pool %s. "
                    wok_log.error(msg % pool_name)
                    wok_log.error("Details: %s", e.message)
                    raise Exception(error_msg)

                # Try to create the pool
                pool = E.pool(E.name(pool_name), type='dir')
                pool.append(E.target(E.path(pool_path)))
                xml = ET.tostring(pool)
                try:
                    pool = conn.storagePoolDefineXML(xml, 0)
                except libvirt.libvirtError, e:
                    msg = "Fatal: Unable to create storage pool %s. "
                    wok_log.error(msg % pool_name)
                    wok_log.error("Details: %s", e.message)
                    raise Exception(error_msg)

                # Build and set autostart value to pool
                # Ignore error as the pool was already successfully created
                try:
                    # Add build step to make sure target directory created
                    # The build process may fail when the pool directory
                    # already exists on system
                    pool.build(libvirt.VIR_STORAGE_POOL_BUILD_NEW)
                    pool.setAutostart(1)
                except:
                    pass

            if pool.isActive() == 0:
                try:
                    pool.create(0)
                except libvirt.libvirtError, e:
                    msg = "Fatal: Unable to craete storage pool %s. "
                    wok_log.error(msg % pool_name)
                    wok_log.error("Details: %s", e.message)
                    raise Exception(error_msg)
Ejemplo n.º 5
0
class StoragePoolsModel(object):
    def __init__(self, **kargs):
        self.conn = kargs['conn']
        self.objstore = kargs['objstore']
        self.scanner = Scanner(self._clean_scan)
        self.scanner.delete()
        self.caps = CapabilitiesModel(**kargs)
        self.device = DeviceModel(**kargs)

        if self.conn.get() is not None:
            if self.conn.isQemuURI():
                self._check_default_pools()

    def _check_default_pools(self):
        pools = {}

        # Don't create default pool if it's not
        # explicitly specified in template.conf
        if is_s390x() and 'pool' not in tmpl_defaults['disks'][0]:
            return

        default_pool = tmpl_defaults['disks'][0]['pool']['name']
        default_pool = default_pool.split('/')[-1]

        pools[default_pool] = {}
        if default_pool == 'default':
            pools[default_pool] = {'path': '/var/lib/libvirt/images'}

        if config.get('kimchi', {}).get('create_iso_pool', False):
            pools['ISO'] = {'path': '/var/lib/kimchi/isos'}

        conn = self.conn.get()
        for pool_name in pools:
            error_msg = ('Storage pool %s does not exist or is not '
                         'active. Please, check the configuration in '
                         '%s/template.conf to ensure it lists only valid '
                         'storage.' % (pool_name, kimchiPaths.sysconf_dir))
            try:
                pool = conn.storagePoolLookupByName(pool_name)
            except libvirt.libvirtError as e:
                pool_path = pools[pool_name].get('path')
                if pool_path is None:
                    wok_log.error(
                        f'Fatal: Unable to find storage pool {pool_name}.')
                    wok_log.error(f'Details: {str(e)}')
                    raise Exception(error_msg)

                # Try to create the pool
                pool = E.pool(E.name(pool_name), type='dir')
                pool.append(E.target(E.path(pool_path)))
                xml = ET.tostring(pool)
                try:
                    pool = conn.storagePoolDefineXML(xml, 0)
                except libvirt.libvirtError as e:
                    wok_log.error(
                        f'Fatal: Unable to create storage pool {pool_name}.')
                    wok_log.error(f'Details: {str(e)}')
                    raise Exception(error_msg)

                # Build and set autostart value to pool
                # Ignore error as the pool was already successfully created
                try:
                    # Add build step to make sure target directory created
                    # The build process may fail when the pool directory
                    # already exists on system
                    pool.build(libvirt.VIR_STORAGE_POOL_BUILD_NEW)
                    pool.setAutostart(1)
                except Exception:
                    pass

            if pool.isActive() == 0:
                try:
                    pool.create(0)
                except libvirt.libvirtError as e:
                    wok_log.error(
                        f'Fatal: Unable to create storage pool {pool_name}.')
                    wok_log.error(f'Details: {str(e)}')
                    raise Exception(error_msg)

    def get_list(self):
        try:
            conn = self.conn.get()
            names = conn.listStoragePools()
            names += conn.listDefinedStoragePools()
            return sorted(names)
        except libvirt.libvirtError as e:
            raise OperationFailed('KCHPOOL0006E',
                                  {'err': e.get_error_message()})

    def _check_lvm(self, name, from_vg):
        vgdisplay_cmd = ['vgdisplay', name]
        output, error, returncode = run_command(vgdisplay_cmd)
        # From vgdisplay error codes:
        # 1  error reading VGDA
        # 2  volume group doesn't exist
        # 3  not all physical volumes of volume group online
        # 4  volume group not found
        # 5  no volume groups found at all
        # 6  error reading VGDA from lvmtab
        if from_vg and returncode in [2, 4, 5]:
            raise InvalidOperation('KCHPOOL0038E', {'name': name})

        if not from_vg and returncode not in [2, 4, 5]:
            raise InvalidOperation('KCHPOOL0036E', {'name': name})

    def create(self, params):
        task_id = None
        conn = self.conn.get()
        from_vg = params.get('source', {}).get('from_vg', False)

        try:
            name = params['name']
            if name == ISO_POOL_NAME:
                raise InvalidOperation('KCHPOOL0031E')

            # The user may want to create a logical pool with the same name
            # used before but a volume group will already exist with this name
            # So check the volume group does not exist to create the pool
            if params['type'] == 'logical':
                self._check_lvm(name, from_vg)

            if params['type'] == 'kimchi-iso':
                task_id = self._do_deep_scan(params)

            if params['type'] == 'scsi':
                adapter_name = params['source']['adapter_name']
                extra_params = self.device.lookup(adapter_name)
                # Adds name, adapter_type, wwpn and wwnn to source information
                params['source'].update(extra_params)
                params['fc_host_support'] = self.caps.fc_host_support

            poolDef = StoragePoolDef.create(params)
            poolDef.prepare(conn)
            xml = poolDef.xml
        except KeyError as item:
            raise MissingParameter('KCHPOOL0004E', {
                'item': str(item),
                'name': name
            })

        if name in self.get_list():
            raise InvalidOperation('KCHPOOL0001E', {'name': name})

        try:
            if task_id:
                # Create transient pool for deep scan
                conn.storagePoolCreateXML(xml, 0)
                return name

            pool = conn.storagePoolDefineXML(xml, 0)
        except libvirt.libvirtError as e:
            wok_log.error(f'Problem creating Storage Pool: {str(e)}')
            raise OperationFailed('KCHPOOL0007E', {
                'name': name,
                'err': e.get_error_message()
            })

        # Build and set autostart value to pool
        # Ignore error as the pool was already successfully created
        # The build process fails when the pool directory already exists
        try:
            if params['type'] in ['logical', 'dir', 'netfs', 'scsi']:
                pool.build(libvirt.VIR_STORAGE_POOL_BUILD_NEW)
                pool.setAutostart(1)
            else:
                pool.setAutostart(0)
        except Exception:
            pass

        if params['type'] == 'netfs':
            output, error, returncode = run_command(
                ['setsebool', '-P', 'virt_use_nfs=1'])
            if error or returncode:
                wok_log.error('Unable to set virt_use_nfs=1. If you use '
                              'SELinux, this may prevent NFS pools from '
                              'being used.')
        return name

    def _clean_scan(self, pool_name):
        try:
            conn = self.conn.get()
            pool = conn.storagePoolLookupByName(pool_name)
            pool.destroy()
            with self.objstore as session:
                session.delete('scanning', pool_name)
        except Exception as e:
            wok_log.debug(f'Exception {e} occurred when cleaning scan result')

    def _do_deep_scan(self, params):
        scan_params = dict(ignore_list=[])
        scan_params['scan_path'] = params['path']
        params['type'] = 'dir'

        for pool in self.get_list():
            try:
                res = StoragePoolModel(conn=self.conn,
                                       objstore=self.objstore).lookup(pool)
                if res['state'] == 'active':
                    scan_params['ignore_list'].append(res['path'])
            except Exception as e:
                wok_log.debug(f'Exception {e} occured when get ignore path')

        params['path'] = self.scanner.scan_dir_prepare(params['name'])
        scan_params['pool_path'] = params['path']
        task_id = AsyncTask(
            f'/plugins/kimchi/storagepools/{ISO_POOL_NAME}',
            self.scanner.start_scan,
            scan_params,
        ).id
        # Record scanning-task/storagepool mapping for future querying
        try:
            with self.objstore as session:
                session.store('scanning', params['name'], task_id,
                              get_kimchi_version())
            return task_id
        except Exception as e:
            raise OperationFailed('KCHPOOL0037E', {'err': e.message})
Ejemplo n.º 6
0
class StoragePoolsModel(object):
    def __init__(self, **kargs):
        self.conn = kargs['conn']
        self.objstore = kargs['objstore']
        self.scanner = Scanner(self._clean_scan)
        self.scanner.delete()
        self.caps = CapabilitiesModel(**kargs)
        self.device = DeviceModel(**kargs)

        if self.conn.get() is not None:
            if self.conn.isQemuURI():
                self._check_default_pools()

    def _check_default_pools(self):
        pools = {}

        # Don't create default pool if it's not
        # explicitly specified in template.conf
        if is_s390x() and 'pool' not in tmpl_defaults['disks'][0]:
            return

        default_pool = tmpl_defaults['disks'][0]['pool']['name']
        default_pool = default_pool.split('/')[-1]

        pools[default_pool] = {}
        if default_pool == 'default':
            pools[default_pool] = {'path': '/var/lib/libvirt/images'}

        if config.get('kimchi', {}).get('create_iso_pool', False):
            pools['ISO'] = {'path': '/var/lib/kimchi/isos'}

        conn = self.conn.get()
        for pool_name in pools:
            error_msg = (
                'Storage pool %s does not exist or is not '
                'active. Please, check the configuration in '
                '%s/template.conf to ensure it lists only valid '
                'storage.' % (pool_name, kimchiPaths.sysconf_dir)
            )
            try:
                pool = conn.storagePoolLookupByName(pool_name)
            except libvirt.libvirtError as e:
                pool_path = pools[pool_name].get('path')
                if pool_path is None:
                    wok_log.error(
                        f'Fatal: Unable to find storage pool {pool_name}.')
                    wok_log.error(f'Details: {str(e)}')
                    raise Exception(error_msg)

                # Try to create the pool
                pool = E.pool(E.name(pool_name), type='dir')
                pool.append(E.target(E.path(pool_path)))
                xml = ET.tostring(pool)
                try:
                    pool = conn.storagePoolDefineXML(xml, 0)
                except libvirt.libvirtError as e:
                    wok_log.error(
                        f'Fatal: Unable to create storage pool {pool_name}.')
                    wok_log.error(f'Details: {str(e)}')
                    raise Exception(error_msg)

                # Build and set autostart value to pool
                # Ignore error as the pool was already successfully created
                try:
                    # Add build step to make sure target directory created
                    # The build process may fail when the pool directory
                    # already exists on system
                    pool.build(libvirt.VIR_STORAGE_POOL_BUILD_NEW)
                    pool.setAutostart(1)
                except Exception:
                    pass

            if pool.isActive() == 0:
                try:
                    pool.create(0)
                except libvirt.libvirtError as e:
                    wok_log.error(
                        f'Fatal: Unable to create storage pool {pool_name}.')
                    wok_log.error(f'Details: {str(e)}')
                    raise Exception(error_msg)

    def get_list(self):
        try:
            conn = self.conn.get()
            names = conn.listStoragePools()
            names += conn.listDefinedStoragePools()
            return sorted(names)
        except libvirt.libvirtError as e:
            raise OperationFailed(
                'KCHPOOL0006E', {'err': e.get_error_message()})

    def _check_lvm(self, name, from_vg):
        vgdisplay_cmd = ['vgdisplay', name]
        output, error, returncode = run_command(vgdisplay_cmd)
        # From vgdisplay error codes:
        # 1  error reading VGDA
        # 2  volume group doesn't exist
        # 3  not all physical volumes of volume group online
        # 4  volume group not found
        # 5  no volume groups found at all
        # 6  error reading VGDA from lvmtab
        if from_vg and returncode in [2, 4, 5]:
            raise InvalidOperation('KCHPOOL0038E', {'name': name})

        if not from_vg and returncode not in [2, 4, 5]:
            raise InvalidOperation('KCHPOOL0036E', {'name': name})

    def create(self, params):
        task_id = None
        conn = self.conn.get()
        from_vg = params.get('source', {}).get('from_vg', False)

        try:
            name = params['name']
            if name == ISO_POOL_NAME:
                raise InvalidOperation('KCHPOOL0031E')

            # The user may want to create a logical pool with the same name
            # used before but a volume group will already exist with this name
            # So check the volume group does not exist to create the pool
            if params['type'] == 'logical':
                self._check_lvm(name, from_vg)

            if params['type'] == 'kimchi-iso':
                task_id = self._do_deep_scan(params)

            if params['type'] == 'scsi':
                adapter_name = params['source']['adapter_name']
                extra_params = self.device.lookup(adapter_name)
                # Adds name, adapter_type, wwpn and wwnn to source information
                params['source'].update(extra_params)
                params['fc_host_support'] = self.caps.fc_host_support

            poolDef = StoragePoolDef.create(params)
            poolDef.prepare(conn)
            xml = poolDef.xml
        except KeyError as item:
            raise MissingParameter(
                'KCHPOOL0004E', {'item': str(item), 'name': name})

        if name in self.get_list():
            raise InvalidOperation('KCHPOOL0001E', {'name': name})

        try:
            if task_id:
                # Create transient pool for deep scan
                conn.storagePoolCreateXML(xml, 0)
                return name

            pool = conn.storagePoolDefineXML(xml, 0)
        except libvirt.libvirtError as e:
            wok_log.error(f'Problem creating Storage Pool: {str(e)}')
            raise OperationFailed(
                'KCHPOOL0007E', {'name': name, 'err': e.get_error_message()}
            )

        # Build and set autostart value to pool
        # Ignore error as the pool was already successfully created
        # The build process fails when the pool directory already exists
        try:
            if params['type'] in ['logical', 'dir', 'netfs', 'scsi']:
                pool.build(libvirt.VIR_STORAGE_POOL_BUILD_NEW)
                pool.setAutostart(1)
            else:
                pool.setAutostart(0)
        except Exception:
            pass

        if params['type'] == 'netfs':
            output, error, returncode = run_command(
                ['setsebool', '-P', 'virt_use_nfs=1']
            )
            if error or returncode:
                wok_log.error(
                    'Unable to set virt_use_nfs=1. If you use '
                    'SELinux, this may prevent NFS pools from '
                    'being used.'
                )
        return name

    def _clean_scan(self, pool_name):
        try:
            conn = self.conn.get()
            pool = conn.storagePoolLookupByName(pool_name)
            pool.destroy()
            with self.objstore as session:
                session.delete('scanning', pool_name)
        except Exception as e:
            wok_log.debug(f'Exception {e} occurred when cleaning scan result')

    def _do_deep_scan(self, params):
        scan_params = dict(ignore_list=[])
        scan_params['scan_path'] = params['path']
        params['type'] = 'dir'

        for pool in self.get_list():
            try:
                res = StoragePoolModel(conn=self.conn, objstore=self.objstore).lookup(
                    pool
                )
                if res['state'] == 'active':
                    scan_params['ignore_list'].append(res['path'])
            except Exception as e:
                wok_log.debug(f'Exception {e} occured when get ignore path')

        params['path'] = self.scanner.scan_dir_prepare(params['name'])
        scan_params['pool_path'] = params['path']
        task_id = AsyncTask(
            f'/plugins/kimchi/storagepools/{ISO_POOL_NAME}',
            self.scanner.start_scan,
            scan_params,
        ).id
        # Record scanning-task/storagepool mapping for future querying
        try:
            with self.objstore as session:
                session.store(
                    'scanning', params['name'], task_id, get_kimchi_version())
            return task_id
        except Exception as e:
            raise OperationFailed('KCHPOOL0037E', {'err': e.message})