55import functools
66import logging
77import os
8+ from dataclasses import dataclass
89
910import lib .commands as commands
1011
1617if TYPE_CHECKING :
1718 from lib .host import Host
1819 from lib .pool import Pool
20+ from lib .sr import SR
21+ from lib .vdi import VDI
1922
2023GROUP_NAME = 'linstor_group'
2124STORAGE_POOL_NAME = f'{ GROUP_NAME } /thin_device'
2225LINSTOR_RELEASE_PACKAGE = 'xcp-ng-release-linstor'
2326LINSTOR_PACKAGE = 'xcp-ng-linstor'
2427
28+ @dataclass
29+ class LinstorConfig :
30+ uninstall_linstor : bool = True
31+
32+ @pytest .fixture (scope = 'package' )
33+ def _linstor_config () -> LinstorConfig :
34+ return LinstorConfig ()
35+
2536@pytest .fixture (scope = 'package' )
26- def lvm_disks (pool_with_unused_512B_disk : Pool ,
27- unused_512B_disks : dict [Host , list [Host .BlockDeviceInfo ]],
28- provisioning_type : str ) -> Generator [None ]:
37+ def lvm_disks (
38+ pool_with_unused_512B_disk : Pool ,
39+ unused_512B_disks : dict [Host , list [Host .BlockDeviceInfo ]],
40+ provisioning_type : str ,
41+ ) -> Generator [None ]:
2942 """
3043 Common LVM PVs on which a LV is created on each host of the pool.
3144
@@ -70,19 +83,24 @@ def host_devices(host: Host) -> list[str]:
7083 host .ssh (['pvremove' , device ])
7184
7285@pytest .fixture (scope = "package" )
73- def storage_pool_name (provisioning_type ) :
86+ def storage_pool_name (provisioning_type : str ) -> str :
7487 return GROUP_NAME if provisioning_type == "thick" else STORAGE_POOL_NAME
7588
7689@pytest .fixture (params = ["thin" ], scope = "session" )
77- def provisioning_type (request ) :
90+ def provisioning_type (request : pytest . FixtureRequest ) -> str :
7891 return request .param
7992
8093@pytest .fixture (scope = 'package' )
81- def pool_with_linstor (hostA2 , lvm_disks , pool_with_saved_yum_state ):
94+ def pool_with_linstor (
95+ hostA2 : Host ,
96+ lvm_disks : None ,
97+ pool_with_saved_yum_state : Pool ,
98+ _linstor_config : LinstorConfig
99+ ) -> Generator [Pool ]:
82100 import concurrent .futures
83101 pool = pool_with_saved_yum_state
84102
85- def check_linstor_installed (host ):
103+ def check_linstor_installed (host : Host ):
86104 if host .is_package_installed (LINSTOR_PACKAGE ):
87105 raise Exception (
88106 f'{ LINSTOR_PACKAGE } is already installed on host { host } . This should not be the case.'
@@ -91,7 +109,7 @@ def check_linstor_installed(host):
91109 with concurrent .futures .ThreadPoolExecutor () as executor :
92110 executor .map (check_linstor_installed , pool .hosts )
93111
94- def install_linstor (host ):
112+ def install_linstor (host : Host ):
95113 logging .info (f"Installing { LINSTOR_PACKAGE } on host { host } ..." )
96114 host .yum_install ([LINSTOR_RELEASE_PACKAGE ])
97115 host .yum_install ([LINSTOR_PACKAGE ], enablerepo = "xcp-ng-linstor-testing" )
@@ -105,9 +123,16 @@ def install_linstor(host):
105123
106124 yield pool
107125
126+ def _disable_yum_rollback (host : Host ):
127+ host .saved_rollback_id = None
128+
129+ if not _linstor_config .uninstall_linstor :
130+ pool .exec_on_hosts_on_error_continue (_disable_yum_rollback )
131+ return
132+
108133 # Need to remove this package as we have separate run of `test_create_sr_without_linstor`
109134 # for `thin` and `thick` `provisioning_type`.
110- def remove_linstor (host ):
135+ def remove_linstor (host : Host ):
111136 logging .info (f"Cleaning up python-linstor from host { host } ..." )
112137 host .yum_remove (["python-linstor" ])
113138 host .restart_toolstack (verify = True )
@@ -116,23 +141,32 @@ def remove_linstor(host):
116141 executor .map (remove_linstor , pool .hosts )
117142
118143@pytest .fixture (scope = 'package' )
119- def linstor_sr (pool_with_linstor , provisioning_type , storage_pool_name ):
144+ def linstor_sr (
145+ pool_with_linstor : Pool ,
146+ provisioning_type : str ,
147+ storage_pool_name : str ,
148+ _linstor_config : LinstorConfig
149+ ) -> Generator [SR ]:
120150 sr = pool_with_linstor .master .sr_create ('linstor' , 'LINSTOR-SR-test' , {
121151 'group-name' : storage_pool_name ,
122152 'redundancy' : str (min (len (pool_with_linstor .hosts ), 3 )),
123153 'provisioning' : provisioning_type
124154 }, shared = True )
125155 yield sr
126- sr .destroy ()
156+ try :
157+ sr .destroy ()
158+ except Exception as e :
159+ _linstor_config .uninstall_linstor = False
160+ raise pytest .fail ("Could not destroy linstor SR, leaving packages in place for manual cleanup" ) from e
127161
128162@pytest .fixture (scope = 'module' )
129- def vdi_on_linstor_sr (linstor_sr ) :
163+ def vdi_on_linstor_sr (linstor_sr : SR ) -> Generator [ VDI ] :
130164 vdi = linstor_sr .create_vdi ('LINSTOR-VDI-test' )
131165 yield vdi
132166 vdi .destroy ()
133167
134168@pytest .fixture (scope = 'module' )
135- def vm_on_linstor_sr (host , linstor_sr , vm_ref ):
169+ def vm_on_linstor_sr (host : Host , linstor_sr : SR , vm_ref : str ):
136170 vm = host .import_vm (vm_ref , sr_uuid = linstor_sr .uuid )
137171 yield vm
138172 logging .info ("<< Destroy VM" )
0 commit comments