2013-10-28 00:59:46 +04:00
# Copyright (C) 2008, 2013 Red Hat, Inc.
2008-08-08 01:37:16 +04:00
# Copyright (C) 2008 Cole Robinson <crobinso@redhat.com>
#
2018-04-04 16:35:41 +03:00
# This work is licensed under the GNU GPLv2 or later.
2018-03-20 22:00:02 +03:00
# See the COPYING file in the top-level directory.
2008-08-08 01:37:16 +04:00
2014-09-12 20:08:44 +04:00
import time
2014-05-20 01:32:22 +04:00
2019-06-17 04:12:39 +03:00
from virtinst import log
2013-09-29 17:31:39 +04:00
from virtinst import pollhelpers
2013-09-20 04:18:12 +04:00
from virtinst import StoragePool , StorageVolume
2013-07-12 18:53:30 +04:00
2014-09-13 00:10:45 +04:00
from . libvirtobject import vmmLibvirtObject
2013-09-20 04:18:12 +04:00
2019-06-08 00:19:23 +03:00
def _pretty_bytes ( val ) :
val = int ( val )
if val > ( 1024 * 1024 * 1024 ) :
return " %2.2f GiB " % ( val / ( 1024.0 * 1024.0 * 1024.0 ) )
else :
return " %2.2f MiB " % ( val / ( 1024.0 * 1024.0 ) )
2019-07-02 23:29:16 +03:00
POOL_TYPE_DESCS = {
StoragePool . TYPE_DIR : _ ( " Filesystem Directory " ) ,
StoragePool . TYPE_FS : _ ( " Pre-Formatted Block Device " ) ,
StoragePool . TYPE_NETFS : _ ( " Network Exported Directory " ) ,
StoragePool . TYPE_LOGICAL : _ ( " LVM Volume Group " ) ,
StoragePool . TYPE_DISK : _ ( " Physical Disk Device " ) ,
StoragePool . TYPE_ISCSI : _ ( " iSCSI Target " ) ,
StoragePool . TYPE_SCSI : _ ( " SCSI Host Adapter " ) ,
StoragePool . TYPE_MPATH : _ ( " Multipath Device Enumerator " ) ,
StoragePool . TYPE_GLUSTER : _ ( " Gluster Filesystem " ) ,
StoragePool . TYPE_RBD : _ ( " RADOS Block Device/Ceph " ) ,
StoragePool . TYPE_ZFS : _ ( " ZFS Pool " ) ,
}
2013-09-20 04:18:12 +04:00
class vmmStorageVolume ( vmmLibvirtObject ) :
def __init__ ( self , conn , backend , key ) :
2013-09-23 16:34:50 +04:00
vmmLibvirtObject . __init__ ( self , conn , backend , key , StorageVolume )
2013-09-20 04:18:12 +04:00
##########################
# Required class methods #
##########################
2015-04-10 16:15:44 +03:00
def _conn_tick_poll_param ( self ) :
2020-08-22 22:04:01 +03:00
return None # pragma: no cover
2015-04-10 16:15:44 +03:00
def class_name ( self ) :
2020-08-22 22:04:01 +03:00
return " volume " # pragma: no cover
2015-04-10 16:15:44 +03:00
2013-09-20 04:18:12 +04:00
def _XMLDesc ( self , flags ) :
2014-05-20 01:32:22 +04:00
try :
return self . _backend . XMLDesc ( flags )
2020-08-20 20:34:01 +03:00
except Exception as e : # pragma: no cover
2019-06-17 04:12:39 +03:00
log . debug ( " XMLDesc for vol= %s failed: %s " ,
2014-05-20 01:32:22 +04:00
self . _backend . key ( ) , e )
raise
2013-09-20 04:18:12 +04:00
2015-04-10 01:02:42 +03:00
def _get_backend_status ( self ) :
return self . _STATUS_ACTIVE
2013-09-20 04:18:12 +04:00
###########
# Actions #
###########
def get_parent_pool ( self ) :
2014-06-03 01:17:47 +04:00
name = self . _backend . storagePoolLookupByVolume ( ) . name ( )
for pool in self . conn . list_pools ( ) :
if pool . get_name ( ) == name :
return pool
2013-09-20 04:18:12 +04:00
2013-09-30 23:23:14 +04:00
def delete ( self , force = True ) :
ignore = force
2013-09-20 04:18:12 +04:00
self . _backend . delete ( 0 )
self . _backend = None
#################
# XML accessors #
#################
2013-12-05 18:17:29 +04:00
def get_key ( self ) :
return self . get_xmlobj ( ) . key or " "
2013-09-20 04:18:12 +04:00
def get_target_path ( self ) :
2013-09-23 16:34:50 +04:00
return self . get_xmlobj ( ) . target_path or " "
2013-09-20 04:18:12 +04:00
def get_format ( self ) :
2013-09-23 16:34:50 +04:00
return self . get_xmlobj ( ) . format
2013-09-20 04:18:12 +04:00
def get_capacity ( self ) :
2013-09-23 16:34:50 +04:00
return self . get_xmlobj ( ) . capacity
2013-09-20 04:18:12 +04:00
def get_pretty_capacity ( self ) :
2019-06-08 00:19:23 +03:00
return _pretty_bytes ( self . get_capacity ( ) )
2008-08-08 01:37:16 +04:00
2013-12-05 18:17:29 +04:00
def get_pretty_name ( self , pooltype ) :
name = self . get_name ( )
if pooltype != " iscsi " :
return name
key = self . get_key ( )
2020-08-20 20:34:01 +03:00
ret = name
if key :
ret + = " ( %s ) " % key
return ret
2013-12-05 18:17:29 +04:00
2013-04-13 22:34:52 +04:00
2010-12-09 20:37:48 +03:00
class vmmStoragePool ( vmmLibvirtObject ) :
2012-05-14 17:24:56 +04:00
__gsignals__ = {
2018-03-15 15:10:09 +03:00
" refreshed " : ( vmmLibvirtObject . RUN_FIRST , None , [ ] )
2012-05-14 17:24:56 +04:00
}
2019-07-02 23:40:11 +03:00
@staticmethod
def supports_volume_creation ( pool_type , clone = False ) :
"""
Returns if pool supports volume creation . If @clone is set to True
returns if pool supports volume cloning ( virVolCreateXMLFrom ) .
"""
supported = [
StoragePool . TYPE_DIR ,
StoragePool . TYPE_FS ,
StoragePool . TYPE_NETFS ,
StoragePool . TYPE_DISK ,
StoragePool . TYPE_LOGICAL ,
StoragePool . TYPE_RBD ,
]
if not clone :
supported . extend ( [
StoragePool . TYPE_ZFS ,
] )
return pool_type in supported
2019-07-02 23:29:16 +03:00
@staticmethod
def pretty_type ( pool_type ) :
return POOL_TYPE_DESCS . get ( pool_type , " %s pool " % pool_type )
@staticmethod
def list_types ( ) :
return sorted ( list ( POOL_TYPE_DESCS . keys ( ) ) )
2013-07-07 16:42:57 +04:00
def __init__ ( self , conn , backend , key ) :
2013-09-23 16:34:50 +04:00
vmmLibvirtObject . __init__ ( self , conn , backend , key , StoragePool )
2010-12-09 20:37:48 +03:00
2014-09-12 20:08:44 +04:00
self . _last_refresh_time = 0
2015-04-11 01:17:29 +03:00
self . _volumes = None
2013-07-07 16:05:23 +04:00
2013-09-20 04:18:12 +04:00
##########################
# Required class methods #
##########################
2015-04-10 16:15:44 +03:00
def _conn_tick_poll_param ( self ) :
return " pollpool "
def class_name ( self ) :
return " pool "
2010-12-09 20:37:48 +03:00
def _XMLDesc ( self , flags ) :
2013-07-07 16:42:57 +04:00
return self . _backend . XMLDesc ( flags )
2010-12-09 20:37:48 +03:00
def _define ( self , xml ) :
2013-07-07 16:42:57 +04:00
return self . conn . define_pool ( xml )
2016-06-15 00:52:40 +03:00
def _using_events ( self ) :
return self . conn . using_storage_pool_events
2015-04-10 01:02:42 +03:00
def _get_backend_status ( self ) :
2020-08-22 21:15:07 +03:00
return ( bool ( self . _backend . isActive ( ) ) and
self . _STATUS_ACTIVE or
self . _STATUS_INACTIVE )
2013-09-20 04:18:12 +04:00
2015-04-10 21:08:25 +03:00
def _init_libvirt_state ( self ) :
2020-08-22 21:15:07 +03:00
super ( ) . _init_libvirt_state ( )
2016-06-21 00:20:53 +03:00
if not self . conn . is_active ( ) :
# We only want to refresh a pool on initial conn startup,
# since the pools may be out of date. But if a storage pool
# shows up while the conn is connected, this means it was
# just 'defined' recently and doesn't need to be refreshed.
2016-06-22 22:58:07 +03:00
self . refresh ( _from_object_init = True )
2015-04-10 21:08:25 +03:00
for vol in self . get_volumes ( ) :
vol . init_libvirt_state ( )
2015-04-11 01:17:29 +03:00
def _invalidate_xml ( self ) :
vmmLibvirtObject . _invalidate_xml ( self )
self . _volumes = None
2018-03-15 14:43:56 +03:00
def _cleanup ( self ) :
vmmLibvirtObject . _cleanup ( self )
2022-02-19 22:04:45 +03:00
for vol in ( self . _volumes or [ ] ) :
2020-11-10 20:41:32 +03:00
vol . cleanup ( )
2018-03-15 14:43:56 +03:00
self . _volumes = None
2008-08-08 01:37:16 +04:00
2015-04-10 01:02:42 +03:00
###########
# Actions #
###########
2013-07-07 19:06:15 +04:00
2015-04-10 01:27:45 +03:00
@vmmLibvirtObject.lifecycle_action
2008-08-08 01:37:16 +04:00
def start ( self ) :
2013-07-07 16:42:57 +04:00
self . _backend . create ( 0 )
2008-08-08 01:37:16 +04:00
2015-04-10 01:27:45 +03:00
@vmmLibvirtObject.lifecycle_action
2008-08-08 01:37:16 +04:00
def stop ( self ) :
2013-07-07 16:42:57 +04:00
self . _backend . destroy ( )
2008-08-08 01:37:16 +04:00
2015-04-10 01:27:45 +03:00
@vmmLibvirtObject.lifecycle_action
2013-10-01 02:26:43 +04:00
def delete ( self , force = True ) :
ignore = force
self . _backend . undefine ( )
2013-07-07 16:42:57 +04:00
self . _backend = None
2008-08-08 01:37:16 +04:00
2016-06-22 22:58:07 +03:00
def refresh ( self , _from_object_init = False ) :
2015-04-10 21:08:25 +03:00
"""
2016-06-22 22:58:07 +03:00
: param _from_object_init : Only used for the refresh ( ) call from
_init_libvirt_state . Tells us to not refresh the XML , since
we just updated it .
2015-04-10 21:08:25 +03:00
"""
2013-07-07 16:42:57 +04:00
if not self . is_active ( ) :
2020-08-22 22:42:08 +03:00
return # pragma: no cover
2010-04-21 18:56:06 +04:00
2013-07-07 16:42:57 +04:00
self . _backend . refresh ( 0 )
2016-06-22 22:58:07 +03:00
if self . _using_events ( ) and not _from_object_init :
# If we are using events, we let the event loop trigger
# the cache update for us. Except if from init_libvirt_state,
# we want the update to be done immediately
return
self . refresh_pool_cache_from_event_loop (
_from_object_init = _from_object_init )
def refresh_pool_cache_from_event_loop ( self , _from_object_init = False ) :
if not _from_object_init :
2019-06-17 02:41:28 +03:00
self . recache_from_event_loop ( )
2015-04-11 01:17:29 +03:00
self . _update_volumes ( force = True )
2014-09-12 02:59:27 +04:00
self . idle_emit ( " refreshed " )
2014-09-12 20:08:44 +04:00
self . _last_refresh_time = time . time ( )
2015-04-09 21:42:25 +03:00
def secs_since_last_refresh ( self ) :
return time . time ( ) - self . _last_refresh_time
2008-09-06 05:53:26 +04:00
2013-09-20 04:18:12 +04:00
###################
# Volume handling #
###################
2020-09-01 19:35:26 +03:00
def get_volume_by_name ( self , name ) :
for vol in self . get_volumes ( ) :
if vol . get_name ( ) == name :
return vol
2014-09-12 17:55:12 +04:00
def get_volumes ( self ) :
2015-04-11 01:17:29 +03:00
self . _update_volumes ( force = False )
2015-04-10 19:52:42 +03:00
return self . _volumes [ : ]
2013-09-20 04:18:12 +04:00
2015-04-11 01:17:29 +03:00
def _update_volumes ( self , force ) :
2008-08-08 01:37:16 +04:00
if not self . is_active ( ) :
2015-04-10 19:52:42 +03:00
self . _volumes = [ ]
2008-08-08 01:37:16 +04:00
return
2015-04-11 01:17:29 +03:00
if not force and self . _volumes is not None :
return
2008-08-08 01:37:16 +04:00
2020-09-01 19:35:26 +03:00
keymap = dict ( ( o . get_name ( ) , o ) for o in self . _volumes or [ ] )
2020-01-24 23:46:02 +03:00
def cb ( obj , key ) :
return vmmStorageVolume ( self . conn , obj , key )
2020-03-30 23:04:12 +03:00
( dummy1 , dummy2 , allvols ) = pollhelpers . fetch_volumes (
2020-01-24 23:46:02 +03:00
self . conn . get_backend ( ) , self . get_backend ( ) , keymap , cb )
2013-09-29 17:31:39 +04:00
self . _volumes = allvols
2013-09-20 04:18:12 +04:00
2015-04-10 01:02:42 +03:00
#########################
# XML/config operations #
#########################
2021-10-04 22:38:24 +03:00
def set_autostart ( self , val ) :
self . _backend . setAutostart ( val )
2015-04-10 01:02:42 +03:00
def get_autostart ( self ) :
return self . _backend . autostart ( )
2013-09-20 04:18:12 +04:00
def get_type ( self ) :
2013-09-23 16:34:50 +04:00
return self . get_xmlobj ( ) . type
2013-09-20 04:18:12 +04:00
def get_target_path ( self ) :
2013-09-23 16:34:50 +04:00
return self . get_xmlobj ( ) . target_path or " "
2013-09-20 04:18:12 +04:00
def get_allocation ( self ) :
2013-09-23 16:34:50 +04:00
return self . get_xmlobj ( ) . allocation
2013-09-20 04:18:12 +04:00
def get_available ( self ) :
2013-09-23 16:34:50 +04:00
return self . get_xmlobj ( ) . available
2013-09-20 04:18:12 +04:00
def get_capacity ( self ) :
2013-09-23 16:34:50 +04:00
return self . get_xmlobj ( ) . capacity
2013-09-20 04:18:12 +04:00
def get_pretty_allocation ( self ) :
2019-06-08 00:19:23 +03:00
return _pretty_bytes ( self . get_allocation ( ) )
2013-09-20 04:18:12 +04:00
def get_pretty_available ( self ) :
2019-06-08 00:19:23 +03:00
return _pretty_bytes ( self . get_available ( ) )