3
3
# Copyright (C) 2019 Linaro Limited
4
4
# Author: Dan Rue <[email protected] >
5
5
#
6
- # Copyright (C) 2019, 2021-2023 Collabora Limited
6
+ # Copyright (C) 2019, 2021-2025 Collabora Limited
7
7
# Author: Guillaume Tucker <[email protected] >
8
8
# Author: Michal Galka <[email protected] >
9
+ # Author: Denys Fedoryshchenko <[email protected] >
9
10
10
11
"""LAVA runtime implementation"""
11
12
12
13
from collections import namedtuple
13
14
import time
15
+ import uuid
14
16
from urllib .parse import urljoin
15
17
16
18
import requests
@@ -300,8 +302,9 @@ class LAVA(Runtime):
300
302
API_VERSION = 'v0.2'
301
303
RestAPIServer = namedtuple ('RestAPIServer' , ['url' , 'session' ])
302
304
303
- def __init__ (self , configs , ** kwargs ):
305
+ def __init__ (self , configs , context = None , ** kwargs ):
304
306
super ().__init__ (configs , ** kwargs )
307
+ self ._context = context
305
308
self ._server = self ._connect ()
306
309
307
310
def _get_priority (self , job ):
@@ -368,6 +371,8 @@ def wait(self, job_object):
368
371
time .sleep (3 )
369
372
370
373
def _connect (self ):
374
+ if not hasattr (self .config , 'url' ) or not self .config .url :
375
+ return self .RestAPIServer (None , None )
371
376
rest_url = f'{ self .config .url } /api/{ self .API_VERSION } /'
372
377
rest_api = self .RestAPIServer (rest_url , requests .Session ())
373
378
rest_api .session .params = {'format' : 'json' , 'limit' : '256' }
@@ -378,6 +383,9 @@ def _connect(self):
378
383
return rest_api
379
384
380
385
def _submit (self , job ):
386
+ if self ._server .url is None :
387
+ return self ._store_job_in_external_storage (job )
388
+
381
389
jobs_url = urljoin (self ._server .url , 'jobs/' )
382
390
job_data = {
383
391
'definition' : job ,
@@ -391,6 +399,36 @@ def _submit(self, job):
391
399
resp .raise_for_status ()
392
400
return resp .json ()['job_ids' ][0 ]
393
401
402
+ def _store_job_in_external_storage (self , job ):
403
+ """Store job in external storage when LAVA server URL is not defined"""
404
+ if not self ._context :
405
+ raise ValueError ("Context is required for external storage but was not provided" )
406
+
407
+ # Get default storage configuration name from TOML [DEFAULT] section
408
+ storage_name = self ._context .get_default_storage_config ()
409
+ if not storage_name :
410
+ # Fallback to first available storage if no default is specified
411
+ storage_names = self ._context .get_storage_names ()
412
+ if not storage_names :
413
+ raise ValueError ("No storage configurations found in context" )
414
+ storage_name = storage_names [0 ]
415
+
416
+ storage = self ._context .init_storage (storage_name )
417
+ if not storage :
418
+ raise ValueError (f"Failed to initialize storage '{ storage_name } '" )
419
+
420
+ # Generate a unique filename for the job
421
+ filename = f"lava_job_definition"
422
+
423
+ # Store the job definition in external storage
424
+ try :
425
+ job_bytes = job .encode ('utf-8' )
426
+ storage .upload_single ((filename , job_bytes ))
427
+ print (f"Job stored in external storage '{ storage_name } ': { filename } " )
428
+ return None
429
+ except Exception as e :
430
+ raise ValueError (f"Failed to store job in external storage: { e } " )
431
+
394
432
395
433
def get_runtime (runtime_config , ** kwargs ):
396
434
"""Get a LAVA runtime object"""
0 commit comments