@@ -1197,9 +1197,17 @@ def check_external_volume(pv_request, host_volumes):
1197
1197
return hvol
1198
1198
1199
1199
1200
+ # Methods starting with 'yield_*' upon not a single entry raise StopIteration
1201
+ # (via return "reason") and upon no entry for a specific scenario yields
1202
+ # None. Caller should handle None gracefully based on the context the info is
1203
+ # required, like:
1204
+ # 1. Is it critical enough to serve the storage to user? Fail fast
1205
+ # 2. Performing health checks or which can be eventually consistent (listvols)?
1206
+ # Handle gracefully
1200
1207
def yield_hostvol_mount ():
1201
1208
"""Yields mount directory where hostvol is mounted"""
1202
1209
host_volumes = get_pv_hosting_volumes ()
1210
+ info_exist = False
1203
1211
for volume in host_volumes :
1204
1212
hvol = volume ['name' ]
1205
1213
mntdir = os .path .join (HOSTVOL_MOUNTDIR , hvol )
@@ -1208,19 +1216,33 @@ def yield_hostvol_mount():
1208
1216
except CommandException as excep :
1209
1217
logging .error (
1210
1218
logf ("Unable to mount volume" , hvol = hvol , excep = excep .args ))
1211
- return
1219
+ # We aren't able to mount this specific hostvol
1220
+ yield None
1212
1221
logging .info (logf ("Volume is mounted successfully" , hvol = hvol ))
1213
- # After mounting a hostvol, start looking for PVC from '/mntdir/info'
1214
- yield os .path .join (mntdir , 'info' )
1222
+ info_path = os .path .join (mntdir , 'info' )
1223
+ if os .path .isdir (info_path ):
1224
+ # After mounting a hostvol, start looking for PVC from '/mnt/<pool>/info'
1225
+ info_exist = True
1226
+ yield info_path
1227
+ if not info_exist :
1228
+ # A generator should yield "something", to signal "StopIteration" if
1229
+ # there's no info file on any pool, there should be empty yield
1230
+ # Note: raise StopIteration =~ return, but return with a reason is
1231
+ # better.
1232
+ return "No storage pool exists"
1215
1233
1216
1234
1217
1235
def yield_pvc_from_mntdir (mntdir ):
1218
1236
"""Yields PVCs from a single mntdir"""
1219
- # Max recursion depth is two subdirs (/<mntdir>/x/y/<pvc-hash-.json>)
1220
- # If 'subvol' exist then max depth will be three subdirs
1237
+ # Max recursion depth is two subdirs (/<mntdir>/x/y/<pvc-name.json>)
1238
+ # If 'subvol/virtblock/rawblock' exist then max depth will be three subdirs
1239
+ if mntdir .endswith ("info" ) and not os .path .isdir (mntdir ):
1240
+ # There might be a chance that this function is used standalone and so
1241
+ # check for 'info' directory exists
1242
+ yield None
1221
1243
for child in os .listdir (mntdir ):
1222
1244
name = os .path .join (mntdir , child )
1223
- if os .path .isdir (name ):
1245
+ if os .path .isdir (name ) and len ( os . listdir ( name )) :
1224
1246
yield from yield_pvc_from_mntdir (name )
1225
1247
elif name .endswith ('json' ):
1226
1248
# Base case we are interested in, the filename ending with '.json'
@@ -1230,15 +1252,27 @@ def yield_pvc_from_mntdir(mntdir):
1230
1252
data = json .loads (handle .read ().strip ())
1231
1253
logging .debug (
1232
1254
logf ("Found a PVC at" , path = file_path , size = data .get ("size" )))
1233
- yield name [name .find ("pvc" ):name .find (".json" )], data .get ("size" ), \
1234
- data .get ("path_prefix" )
1255
+ data ["name" ] = name [name .rfind ("/" ) + 1 :name .rfind (".json" )]
1256
+ yield data
1257
+ else :
1258
+ # If leaf is neither a json file nor a directory with contents
1259
+ yield None
1235
1260
1236
1261
1237
1262
def yield_pvc_from_hostvol ():
1238
1263
"""Yields a single PVC sequentially from all the hostvolumes"""
1264
+ pvc_exist = False
1239
1265
for mntdir in yield_hostvol_mount ():
1240
- pvcs = yield_pvc_from_mntdir (mntdir )
1241
- yield from pvcs
1266
+ if mntdir is not None :
1267
+ # Only yield PVC if we are able to mount corresponding pool
1268
+ pvc = yield_pvc_from_mntdir (mntdir )
1269
+ for data in pvc :
1270
+ if data is not None :
1271
+ pvc_exist = True
1272
+ data ["mntdir" ] = os .path .dirname (mntdir .strip ("/" ))
1273
+ yield data
1274
+ if not pvc_exist :
1275
+ return "No PVC exist in any storage pool"
1242
1276
1243
1277
1244
1278
def wrap_pvc (pvc_gen ):
@@ -1249,18 +1283,19 @@ def wrap_pvc(pvc_gen):
1249
1283
gen = pvc_gen ()
1250
1284
try :
1251
1285
prev = next (gen )
1252
- except StopIteration :
1253
- return
1254
- for value in gen :
1255
- yield prev , False
1256
- prev = value
1257
- yield prev , True
1258
-
1286
+ for value in gen :
1287
+ yield prev , False
1288
+ prev = value
1289
+ yield prev , True
1290
+ except StopIteration as errmsg :
1291
+ return errmsg
1259
1292
1260
1293
def yield_list_of_pvcs (max_entries = 0 ):
1261
1294
"""Yields list of PVCs limited at 'max_entries'"""
1262
- # List of tuples containing PVC Name and Size
1295
+ # List of dicts containing data of PVC from info_file (with extra keys,
1296
+ # 'name', 'mntdir')
1263
1297
pvcs = []
1298
+ idx = - 1
1264
1299
for idx , value in enumerate (wrap_pvc (yield_pvc_from_hostvol )):
1265
1300
pvc , last = value
1266
1301
token = "" if last else str (idx )
@@ -1279,10 +1314,12 @@ def yield_list_of_pvcs(max_entries=0):
1279
1314
logging .debug (logf ("Received token" , next_token = next_token ))
1280
1315
if next_token and not last and (int (next_token ) !=
1281
1316
int (token ) - max_entries ):
1282
- return
1317
+ return "Incorrect token supplied"
1283
1318
logging .debug (
1284
1319
logf ("Yielding PVC set and next token is " ,
1285
1320
token = token ,
1286
1321
pvcs = pvcs ))
1287
1322
yield pvcs , token
1288
1323
pvcs *= 0
1324
+ if idx == - 1 :
1325
+ return "No PVC exist in any storage pool"
0 commit comments