2022-08-22 12:12:33 +00:00
|
|
|
import contextlib
|
|
|
|
|
2015-02-27 08:53:51 +00:00
|
|
|
from vrtManager import util
|
|
|
|
from vrtManager.connection import wvmConnect
|
|
|
|
|
|
|
|
|
|
|
|
class wvmStorages(wvmConnect):
|
|
|
|
def get_storages_info(self):
|
|
|
|
get_storages = self.get_storages()
|
|
|
|
storages = []
|
|
|
|
for pool in get_storages:
|
|
|
|
stg = self.get_storage(pool)
|
|
|
|
stg_status = stg.isActive()
|
|
|
|
stg_type = util.get_xml_path(stg.XMLDesc(0), "/pool/@type")
|
2022-08-22 12:12:33 +00:00
|
|
|
stg_vol = len(stg.listVolumes()) if stg_status else None
|
2015-02-27 08:53:51 +00:00
|
|
|
stg_size = stg.info()[1]
|
2020-09-25 12:57:17 +00:00
|
|
|
storages.append(
|
2022-11-02 05:54:35 +00:00
|
|
|
{
|
|
|
|
"name": pool,
|
|
|
|
"status": stg_status,
|
|
|
|
"type": stg_type,
|
|
|
|
"volumes": stg_vol,
|
|
|
|
"size": stg_size,
|
|
|
|
}
|
2020-09-25 12:57:17 +00:00
|
|
|
)
|
2015-02-27 08:53:51 +00:00
|
|
|
return storages
|
|
|
|
|
|
|
|
def define_storage(self, xml, flag):
|
|
|
|
self.wvm.storagePoolDefineXML(xml, flag)
|
|
|
|
|
2023-04-27 13:04:43 +00:00
|
|
|
def get_pool_by_target(self, target):
|
|
|
|
pool_names = self.get_storages()
|
|
|
|
for pool_name in pool_names:
|
|
|
|
stg = wvmStorage(self.host, self.login, self.passwd, self.conn, pool_name)
|
|
|
|
if stg.get_target_path() == target:
|
|
|
|
return self.get_storage(pool_name)
|
|
|
|
return None
|
|
|
|
|
2015-02-27 08:53:51 +00:00
|
|
|
def create_storage(self, stg_type, name, source, target):
|
2020-05-21 13:17:25 +00:00
|
|
|
xml = f"""<pool type='{stg_type}'>
|
|
|
|
<name>{name}</name>"""
|
2020-09-25 12:57:17 +00:00
|
|
|
if stg_type == "logical":
|
2020-05-21 13:17:25 +00:00
|
|
|
xml += f"""<source>
|
|
|
|
<device path='{source}'/>
|
|
|
|
<name>{name}</name>
|
|
|
|
<format type='lvm2'/>
|
|
|
|
</source>"""
|
2020-09-25 12:57:17 +00:00
|
|
|
if stg_type == "logical":
|
2022-08-22 12:12:33 +00:00
|
|
|
target = f"/dev/{name}"
|
2020-05-21 13:17:25 +00:00
|
|
|
xml += f"""
|
2015-02-27 08:53:51 +00:00
|
|
|
<target>
|
2020-05-21 13:17:25 +00:00
|
|
|
<path>{target}</path>
|
2015-02-27 08:53:51 +00:00
|
|
|
</target>
|
2020-05-21 13:17:25 +00:00
|
|
|
</pool>"""
|
2015-02-27 08:53:51 +00:00
|
|
|
self.define_storage(xml, 0)
|
|
|
|
stg = self.get_storage(name)
|
2020-09-25 12:57:17 +00:00
|
|
|
if stg_type == "logical":
|
2015-02-27 08:53:51 +00:00
|
|
|
stg.build(0)
|
|
|
|
stg.create(0)
|
|
|
|
stg.setAutostart(1)
|
|
|
|
|
2019-12-19 09:03:25 +00:00
|
|
|
return stg
|
|
|
|
|
2022-11-02 05:54:35 +00:00
|
|
|
def create_storage_ceph(
|
|
|
|
self, stg_type, name, ceph_pool, ceph_host, ceph_user, secret
|
|
|
|
):
|
2020-05-21 13:17:25 +00:00
|
|
|
xml = f"""
|
|
|
|
<pool type='{stg_type}'>
|
|
|
|
<name>{name}</name>
|
2015-02-27 08:53:51 +00:00
|
|
|
<source>
|
2020-05-21 13:17:25 +00:00
|
|
|
<name>{ceph_pool}</name>
|
|
|
|
<host name='{ceph_host}' port='6789'/>
|
|
|
|
<auth username='{ceph_user}' type='ceph'>
|
|
|
|
<secret uuid='{secret}'/>
|
2015-02-27 08:53:51 +00:00
|
|
|
</auth>
|
|
|
|
</source>
|
2020-05-21 13:17:25 +00:00
|
|
|
</pool>
|
|
|
|
"""
|
2015-02-27 08:53:51 +00:00
|
|
|
self.define_storage(xml, 0)
|
|
|
|
stg = self.get_storage(name)
|
|
|
|
stg.create(0)
|
|
|
|
stg.setAutostart(1)
|
|
|
|
|
2022-11-02 05:54:35 +00:00
|
|
|
def create_storage_netfs(
|
|
|
|
self, stg_type, name, netfs_host, source, source_format, target
|
|
|
|
):
|
2020-05-21 13:17:25 +00:00
|
|
|
xml = f"""
|
|
|
|
<pool type='{stg_type}'>
|
|
|
|
<name>{name}</name>
|
2015-02-27 08:53:51 +00:00
|
|
|
<source>
|
2020-05-21 13:17:25 +00:00
|
|
|
<host name='{netfs_host}'/>
|
|
|
|
<dir path='{source}'/>
|
|
|
|
<format type='{source_format}'/>
|
2015-02-27 08:53:51 +00:00
|
|
|
</source>
|
|
|
|
<target>
|
2020-05-21 13:17:25 +00:00
|
|
|
<path>{target}</path>
|
2015-02-27 08:53:51 +00:00
|
|
|
</target>
|
2020-05-21 13:17:25 +00:00
|
|
|
</pool>
|
|
|
|
"""
|
2015-02-27 08:53:51 +00:00
|
|
|
self.define_storage(xml, 0)
|
|
|
|
stg = self.get_storage(name)
|
|
|
|
stg.create(0)
|
|
|
|
stg.setAutostart(1)
|
|
|
|
|
2019-12-19 09:03:25 +00:00
|
|
|
return stg
|
|
|
|
|
2015-02-27 08:53:51 +00:00
|
|
|
|
|
|
|
class wvmStorage(wvmConnect):
|
|
|
|
def __init__(self, host, login, passwd, conn, pool):
|
|
|
|
wvmConnect.__init__(self, host, login, passwd, conn)
|
|
|
|
self.pool = self.get_storage(pool)
|
|
|
|
|
|
|
|
def get_name(self):
|
|
|
|
return self.pool.name()
|
|
|
|
|
|
|
|
def get_status(self):
|
2022-11-02 05:54:35 +00:00
|
|
|
status = [
|
|
|
|
"Not running",
|
|
|
|
"Initializing pool, not available",
|
|
|
|
"Running normally",
|
|
|
|
"Running degraded",
|
|
|
|
]
|
2015-02-27 08:53:51 +00:00
|
|
|
try:
|
|
|
|
return status[self.pool.info()[0]]
|
|
|
|
except ValueError:
|
2020-09-25 12:57:17 +00:00
|
|
|
return "Unknown"
|
2015-02-27 08:53:51 +00:00
|
|
|
|
|
|
|
def get_size(self):
|
|
|
|
return [self.pool.info()[1], self.pool.info()[3]]
|
|
|
|
|
|
|
|
def _XMLDesc(self, flags):
|
|
|
|
return self.pool.XMLDesc(flags)
|
|
|
|
|
|
|
|
def _createXML(self, xml, flags):
|
|
|
|
self.pool.createXML(xml, flags)
|
|
|
|
|
|
|
|
def _createXMLFrom(self, xml, vol, flags):
|
|
|
|
self.pool.createXMLFrom(xml, vol, flags)
|
|
|
|
|
|
|
|
def _define(self, xml):
|
|
|
|
return self.wvm.storagePoolDefineXML(xml, 0)
|
|
|
|
|
|
|
|
def is_active(self):
|
|
|
|
return self.pool.isActive()
|
|
|
|
|
|
|
|
def get_uuid(self):
|
|
|
|
return self.pool.UUIDString()
|
|
|
|
|
|
|
|
def start(self):
|
2022-08-22 12:12:33 +00:00
|
|
|
return self.pool.create(0)
|
2015-02-27 08:53:51 +00:00
|
|
|
|
|
|
|
def stop(self):
|
2022-08-22 12:12:33 +00:00
|
|
|
return self.pool.destroy()
|
2015-02-27 08:53:51 +00:00
|
|
|
|
|
|
|
def delete(self):
|
|
|
|
self.pool.undefine()
|
|
|
|
|
|
|
|
def get_autostart(self):
|
|
|
|
return self.pool.autostart()
|
|
|
|
|
|
|
|
def set_autostart(self, value):
|
|
|
|
self.pool.setAutostart(value)
|
|
|
|
|
|
|
|
def get_type(self):
|
|
|
|
return util.get_xml_path(self._XMLDesc(0), "/pool/@type")
|
|
|
|
|
|
|
|
def get_target_path(self):
|
|
|
|
return util.get_xml_path(self._XMLDesc(0), "/pool/target/path")
|
|
|
|
|
2021-12-16 08:03:03 +00:00
|
|
|
def get_source_name(self):
|
|
|
|
return util.get_xml_path(self._XMLDesc(0), "/pool/source/name")
|
|
|
|
|
2015-02-27 08:53:51 +00:00
|
|
|
def get_allocation(self):
|
2020-03-16 13:59:45 +00:00
|
|
|
return int(util.get_xml_path(self._XMLDesc(0), "/pool/allocation"))
|
2015-02-27 08:53:51 +00:00
|
|
|
|
|
|
|
def get_available(self):
|
2020-03-16 13:59:45 +00:00
|
|
|
return int(util.get_xml_path(self._XMLDesc(0), "/pool/available"))
|
2015-02-27 08:53:51 +00:00
|
|
|
|
|
|
|
def get_capacity(self):
|
2020-03-16 13:59:45 +00:00
|
|
|
return int(util.get_xml_path(self._XMLDesc(0), "/pool/capacity"))
|
2015-02-27 08:53:51 +00:00
|
|
|
|
2021-12-16 08:03:03 +00:00
|
|
|
def get_rbd_source(self):
|
|
|
|
def hosts(doc):
|
|
|
|
hosts_array = []
|
|
|
|
|
|
|
|
for host in doc.xpath("/pool/source/host"):
|
2022-11-02 05:54:35 +00:00
|
|
|
name = host.get("name")
|
2021-12-16 08:03:03 +00:00
|
|
|
if name:
|
2022-11-02 05:54:35 +00:00
|
|
|
port = host.get("port")
|
2021-12-16 08:03:03 +00:00
|
|
|
if port:
|
|
|
|
hosts_array.append({"hostname": name, "hostport": port})
|
|
|
|
else:
|
|
|
|
hosts_array.append({"hostname": name})
|
|
|
|
|
2022-11-02 05:54:35 +00:00
|
|
|
name = doc.get("name")
|
2021-12-16 08:03:03 +00:00
|
|
|
auth = doc.xpath("/pool/source/auth")
|
|
|
|
auth_type = auth[0].get("type")
|
|
|
|
auth_user = auth[0].get("username")
|
|
|
|
auth_uuid = auth[0].xpath("secret/@uuid")[0]
|
|
|
|
|
2022-11-02 05:54:35 +00:00
|
|
|
return {
|
2021-12-16 08:03:03 +00:00
|
|
|
"name": name,
|
|
|
|
"auth_type": auth_type,
|
|
|
|
"auth_user": auth_user,
|
|
|
|
"auth_uuid": auth_uuid,
|
2022-11-02 05:54:35 +00:00
|
|
|
"hosts": hosts_array,
|
|
|
|
}
|
|
|
|
|
2021-12-16 08:03:03 +00:00
|
|
|
return util.get_xml_path(self._XMLDesc(0), func=hosts)
|
|
|
|
|
2015-02-27 08:53:51 +00:00
|
|
|
def get_pretty_allocation(self):
|
|
|
|
return util.pretty_bytes(self.get_allocation())
|
|
|
|
|
|
|
|
def get_pretty_available(self):
|
|
|
|
return util.pretty_bytes(self.get_available())
|
|
|
|
|
|
|
|
def get_pretty_capacity(self):
|
|
|
|
return util.pretty_bytes(self.get_capacity())
|
|
|
|
|
|
|
|
def get_volumes(self):
|
|
|
|
return self.pool.listVolumes()
|
|
|
|
|
|
|
|
def get_volume(self, name):
|
|
|
|
return self.pool.storageVolLookupByName(name)
|
|
|
|
|
|
|
|
def get_volume_size(self, name):
|
|
|
|
vol = self.get_volume(name)
|
|
|
|
return vol.info()[1]
|
|
|
|
|
2018-07-25 06:37:38 +00:00
|
|
|
def get_volume_allocation(self, name):
|
|
|
|
vol = self.get_volume(name)
|
|
|
|
return vol.info()[2]
|
|
|
|
|
2015-02-27 08:53:51 +00:00
|
|
|
def _vol_XMLDesc(self, name):
|
|
|
|
vol = self.get_volume(name)
|
|
|
|
return vol.XMLDesc(0)
|
|
|
|
|
|
|
|
def del_volume(self, name):
|
|
|
|
vol = self.pool.storageVolLookupByName(name)
|
|
|
|
vol.delete(0)
|
|
|
|
|
2021-12-16 08:03:03 +00:00
|
|
|
def get_volume_format_type(self, name):
|
2015-02-27 08:53:51 +00:00
|
|
|
vol_xml = self._vol_XMLDesc(name)
|
|
|
|
return util.get_xml_path(vol_xml, "/volume/target/format/@type")
|
|
|
|
|
2021-12-16 08:03:03 +00:00
|
|
|
def get_volume_type(self, name):
|
|
|
|
vol_xml = self._vol_XMLDesc(name)
|
|
|
|
return util.get_xml_path(vol_xml, "/volume/@type")
|
|
|
|
|
2015-02-27 08:53:51 +00:00
|
|
|
def refresh(self):
|
2022-08-22 12:12:33 +00:00
|
|
|
return self.pool.refresh(0)
|
2015-02-27 08:53:51 +00:00
|
|
|
|
2022-11-02 13:05:41 +00:00
|
|
|
def get_volumes_details(self):
|
2022-08-22 12:34:51 +00:00
|
|
|
with contextlib.suppress(Exception):
|
2015-02-27 08:53:51 +00:00
|
|
|
self.refresh()
|
2022-08-22 12:12:33 +00:00
|
|
|
|
2022-08-22 12:34:51 +00:00
|
|
|
vols = self.get_volumes()
|
2022-11-02 05:54:35 +00:00
|
|
|
return [
|
|
|
|
{
|
2022-08-22 12:12:33 +00:00
|
|
|
"name": volname,
|
|
|
|
"size": self.get_volume_size(volname),
|
|
|
|
"allocation": self.get_volume_allocation(volname),
|
|
|
|
"type": self.get_volume_format_type(volname),
|
2022-11-02 05:54:35 +00:00
|
|
|
}
|
|
|
|
for volname in vols
|
|
|
|
]
|
|
|
|
|
|
|
|
def get_volume_details(self, volname):
|
|
|
|
with contextlib.suppress(Exception):
|
|
|
|
self.refresh()
|
|
|
|
return {
|
|
|
|
"name": volname,
|
|
|
|
"size": self.get_volume_size(volname),
|
|
|
|
"allocation": self.get_volume_allocation(volname),
|
|
|
|
"type": self.get_volume_format_type(volname),
|
2022-08-22 12:12:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
def update_volumes(self):
|
|
|
|
with contextlib.suppress(Exception):
|
|
|
|
self.refresh()
|
2015-02-27 08:53:51 +00:00
|
|
|
vols = self.get_volumes()
|
2022-11-02 05:54:35 +00:00
|
|
|
return [
|
|
|
|
{
|
|
|
|
"name": volname,
|
|
|
|
"size": self.get_volume_size(volname),
|
|
|
|
"allocation": self.get_volume_allocation(volname),
|
|
|
|
"type": self.get_volume_format_type(volname),
|
|
|
|
}
|
|
|
|
for volname in vols
|
|
|
|
]
|
|
|
|
|
|
|
|
def create_volume(
|
|
|
|
self,
|
|
|
|
name,
|
|
|
|
size,
|
|
|
|
vol_fmt="qcow2",
|
|
|
|
metadata=False,
|
|
|
|
disk_owner_uid=0,
|
|
|
|
disk_owner_gid=0,
|
|
|
|
):
|
2015-02-27 08:53:51 +00:00
|
|
|
size = int(size) * 1073741824
|
|
|
|
storage_type = self.get_type()
|
|
|
|
alloc = size
|
2020-09-25 12:57:17 +00:00
|
|
|
if vol_fmt == "unknown":
|
|
|
|
vol_fmt = "raw"
|
|
|
|
if storage_type == "dir":
|
2022-08-22 12:12:33 +00:00
|
|
|
name += f".{vol_fmt}" if vol_fmt in ("qcow", "qcow2") else ".img"
|
2015-02-27 08:53:51 +00:00
|
|
|
alloc = 0
|
2020-05-21 13:17:25 +00:00
|
|
|
xml = f"""
|
2015-02-27 08:53:51 +00:00
|
|
|
<volume>
|
2020-05-21 13:17:25 +00:00
|
|
|
<name>{name}</name>
|
|
|
|
<capacity>{size}</capacity>
|
|
|
|
<allocation>{alloc}</allocation>
|
2015-02-27 08:53:51 +00:00
|
|
|
<target>
|
2020-05-21 13:17:25 +00:00
|
|
|
<format type='{vol_fmt}'/>
|
2018-07-25 06:37:38 +00:00
|
|
|
<permissions>
|
2020-05-28 21:43:26 +00:00
|
|
|
<owner>{disk_owner_uid}</owner>
|
|
|
|
<group>{disk_owner_gid}</group>
|
2018-07-25 06:37:38 +00:00
|
|
|
<mode>0644</mode>
|
|
|
|
<label>virt_image_t</label>
|
2020-05-21 13:17:25 +00:00
|
|
|
</permissions>"""
|
2020-09-25 12:57:17 +00:00
|
|
|
if vol_fmt == "qcow2":
|
2019-04-29 11:09:17 +00:00
|
|
|
xml += """
|
|
|
|
<compat>1.1</compat>
|
|
|
|
<features>
|
|
|
|
<lazy_refcounts/>
|
|
|
|
</features>"""
|
2020-05-21 13:17:25 +00:00
|
|
|
xml += """</target>
|
2019-04-29 11:09:17 +00:00
|
|
|
</volume>"""
|
2015-02-27 08:53:51 +00:00
|
|
|
self._createXML(xml, metadata)
|
2019-04-29 11:09:17 +00:00
|
|
|
return name
|
2015-02-27 08:53:51 +00:00
|
|
|
|
2020-11-05 09:34:31 +00:00
|
|
|
def clone_volume(
|
|
|
|
self,
|
|
|
|
name,
|
|
|
|
target_file,
|
|
|
|
vol_fmt=None,
|
|
|
|
metadata=False,
|
|
|
|
mode="0644",
|
|
|
|
file_suffix="img",
|
|
|
|
disk_owner_uid=0,
|
|
|
|
disk_owner_gid=0,
|
|
|
|
):
|
2015-02-27 08:53:51 +00:00
|
|
|
vol = self.get_volume(name)
|
|
|
|
if not vol_fmt:
|
2021-12-16 08:03:03 +00:00
|
|
|
vol_fmt = self.get_volume_format_type(name)
|
2019-04-29 11:09:17 +00:00
|
|
|
|
|
|
|
storage_type = self.get_type()
|
2020-09-25 12:57:17 +00:00
|
|
|
if storage_type == "dir":
|
|
|
|
if vol_fmt in ["qcow", "qcow2"]:
|
2022-08-22 12:12:33 +00:00
|
|
|
target_file += f".{vol_fmt}"
|
2019-04-29 11:09:17 +00:00
|
|
|
else:
|
2022-08-22 12:12:33 +00:00
|
|
|
suffix = f".{file_suffix}"
|
2020-11-05 09:34:31 +00:00
|
|
|
target_file += suffix if len(suffix) > 1 else ""
|
2019-04-29 11:09:17 +00:00
|
|
|
|
2020-05-21 13:17:25 +00:00
|
|
|
xml = f"""
|
2015-02-27 08:53:51 +00:00
|
|
|
<volume>
|
2020-05-21 13:17:25 +00:00
|
|
|
<name>{target_file}</name>
|
2015-02-27 08:53:51 +00:00
|
|
|
<capacity>0</capacity>
|
|
|
|
<allocation>0</allocation>
|
|
|
|
<target>
|
2020-05-21 13:17:25 +00:00
|
|
|
<format type='{vol_fmt}'/>
|
2018-07-25 06:37:38 +00:00
|
|
|
<permissions>
|
2020-05-28 21:43:26 +00:00
|
|
|
<owner>{disk_owner_uid}</owner>
|
|
|
|
<group>{disk_owner_gid}</group>
|
2020-05-21 13:17:25 +00:00
|
|
|
<mode>{mode}</mode>
|
2018-07-25 06:37:38 +00:00
|
|
|
<label>virt_image_t</label>
|
2020-05-21 13:17:25 +00:00
|
|
|
</permissions>"""
|
2020-09-25 12:57:17 +00:00
|
|
|
if vol_fmt == "qcow2":
|
2019-04-29 11:09:17 +00:00
|
|
|
xml += """
|
2018-07-31 13:26:28 +00:00
|
|
|
<compat>1.1</compat>
|
|
|
|
<features>
|
|
|
|
<lazy_refcounts/>
|
2019-04-29 11:09:17 +00:00
|
|
|
</features>"""
|
|
|
|
xml += """ </target>
|
|
|
|
</volume>"""
|
2015-02-27 08:53:51 +00:00
|
|
|
self._createXMLFrom(xml, vol, metadata)
|
2019-04-29 11:09:17 +00:00
|
|
|
return target_file
|