2023-09-02 00:52:28 +03:00
|
|
|
import logging
|
2023-09-23 21:24:56 +03:00
|
|
|
from collections import namedtuple
|
2023-09-02 00:52:28 +03:00
|
|
|
|
2023-08-27 23:42:56 +03:00
|
|
|
import libvirt
|
2023-09-23 21:24:56 +03:00
|
|
|
from lxml import etree
|
2023-08-27 23:42:56 +03:00
|
|
|
|
2023-09-02 00:52:28 +03:00
|
|
|
from ..exceptions import StoragePoolError
|
2023-08-31 20:37:41 +03:00
|
|
|
from .volume import Volume, VolumeInfo
|
|
|
|
|
2023-08-27 23:42:56 +03:00
|
|
|
|
2023-09-02 00:52:28 +03:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
2023-08-27 23:42:56 +03:00
|
|
|
class StoragePool:
|
|
|
|
def __init__(self, pool: libvirt.virStoragePool):
|
|
|
|
self.pool = pool
|
|
|
|
|
2023-08-31 20:37:41 +03:00
|
|
|
@property
|
|
|
|
def name(self) -> str:
|
|
|
|
return self.pool.name()
|
|
|
|
|
2023-09-23 21:24:56 +03:00
|
|
|
@property
|
|
|
|
def path(self) -> str:
|
|
|
|
xml = etree.fromstring(self.pool.XMLDesc())
|
|
|
|
return xml.xpath('/pool/target/path/text()')[0]
|
2023-08-31 20:37:41 +03:00
|
|
|
|
2023-09-23 21:24:56 +03:00
|
|
|
@property
|
|
|
|
def usage(self) -> 'StoragePoolUsage':
|
|
|
|
xml = etree.fromstring(self.pool.XMLDesc())
|
|
|
|
StoragePoolUsage = namedtuple('StoagePoolUsage',
|
|
|
|
['capacity', 'allocation', 'available'])
|
|
|
|
return StoragePoolUsage(
|
|
|
|
capacity=int(xml.xpath('/pool/capacity/text()')[0])
|
|
|
|
allocation=int(xml.xpath('/pool/allocation/text()')[0])
|
|
|
|
available=int(xml.xpath('/pool/available/text()')[0]))
|
2023-08-31 20:37:41 +03:00
|
|
|
|
2023-09-23 21:24:56 +03:00
|
|
|
def dump_xml(self) -> str:
|
|
|
|
return self.pool.XMLDesc()
|
2023-08-31 20:37:41 +03:00
|
|
|
|
|
|
|
def refresh(self) -> None:
|
|
|
|
self.pool.refresh()
|
|
|
|
|
2023-09-02 00:52:28 +03:00
|
|
|
def create_volume(self, vol_info: VolumeInfo) -> Volume:
|
|
|
|
"""
|
|
|
|
Create storage volume and return Volume instance.
|
|
|
|
"""
|
2023-09-23 21:24:56 +03:00
|
|
|
logger.info('Create storage volume vol=%s in pool=%s',
|
|
|
|
vol_info.name, self.pool)
|
2023-09-02 00:52:28 +03:00
|
|
|
vol = self.pool.createXML(
|
2023-08-31 20:37:41 +03:00
|
|
|
vol_info.to_xml(),
|
|
|
|
flags=libvirt.VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA)
|
|
|
|
return Volume(self.pool, vol)
|
|
|
|
|
2023-09-02 00:52:28 +03:00
|
|
|
def get_volume(self, name: str) -> Volume | None:
|
2023-09-23 21:24:56 +03:00
|
|
|
"""Lookup and return Volume instance or None."""
|
|
|
|
logger.info('Lookup for storage volume vol=%s in pool=%s',
|
|
|
|
name, self.pool.name)
|
2023-09-02 00:52:28 +03:00
|
|
|
try:
|
|
|
|
vol = self.pool.storageVolLookupByName(name)
|
|
|
|
return Volume(self.pool, vol)
|
|
|
|
except libvirt.libvirtError as err:
|
2023-09-23 21:24:56 +03:00
|
|
|
if (err.get_error_domain() == libvirt.VIR_FROM_STORAGE or
|
|
|
|
err.get_error_code() == libvirt.VIR_ERR_NO_STORAGE_VOL):
|
2023-09-02 00:52:28 +03:00
|
|
|
logger.error(err.get_error_message())
|
|
|
|
return None
|
2023-09-23 21:24:56 +03:00
|
|
|
logger.error('libvirt error: %s' err)
|
|
|
|
raise StoragePoolError(f'libvirt error: {err}') from err
|
2023-09-02 00:52:28 +03:00
|
|
|
|
2023-08-31 20:37:41 +03:00
|
|
|
def list_volumes(self) -> list[Volume]:
|
|
|
|
return [Volume(self.pool, vol) for vol in self.pool.listAllVolumes()]
|