Skip to content

Commit 607a1b3

Browse files
authored
Merge pull request #10 from anyvm-org/dev
sync
2 parents 8adab20 + aa7447c commit 607a1b3

File tree

1 file changed

+95
-29
lines changed

1 file changed

+95
-29
lines changed

anyvm.py

Lines changed: 95 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2971,6 +2971,7 @@ def main():
29712971
cpu_specified = False
29722972
serial_user_specified = False
29732973
vnc_user_specified = False
2974+
arch_specified = False
29742975

29752976

29762977
script_home = os.path.dirname(os.path.abspath(__file__))
@@ -3002,6 +3003,7 @@ def main():
30023003
i += 1
30033004
elif arg == "--arch":
30043005
config['arch'] = args[i+1].lower()
3006+
arch_specified = True
30053007
i += 1
30063008
elif arg == "--mem":
30073009
config['mem'] = args[i+1]
@@ -3170,19 +3172,21 @@ def main():
31703172
# Fetch release info
31713173
releases_cache = {}
31723174

3173-
def get_releases(repo_slug):
3175+
def get_releases(repo_slug, force_refresh=False):
31743176
cache_name = "{}-releases.json".format(repo_slug.replace("/", "_"))
31753177
cache_path = os.path.join(working_dir_os, cache_name)
3176-
if repo_slug in releases_cache:
3178+
if not force_refresh and repo_slug in releases_cache:
31773179
return releases_cache[repo_slug]
3178-
if os.path.exists(cache_path):
3180+
if not force_refresh and os.path.exists(cache_path):
31793181
try:
31803182
with open(cache_path, 'r') as f:
31813183
releases_cache[repo_slug] = json.load(f)
31823184
return releases_cache[repo_slug]
31833185
except ValueError:
31843186
pass
31853187

3188+
debuglog(config['debug'], "Fetching fresh releases for {} (force_refresh={})".format(repo_slug, force_refresh))
3189+
31863190
gh_headers = {
31873191
"Accept": "application/vnd.github+json",
31883192
}
@@ -3246,6 +3250,29 @@ def get_releases(repo_slug):
32463250
debuglog(config['debug'], "Candidate URL (xz) exists!")
32473251
use_this_builder = True
32483252
found_zst_link = candidate_url_xz
3253+
elif config['arch'] == "aarch64" and not arch_specified:
3254+
# Fallback to x86_64 if aarch64 failed and arch was not user-specified
3255+
log("No aarch64 image found for {} {} in {}. Trying x86_64 fallback...".format(config['os'], config['release'], search_repo))
3256+
config['arch'] = "" # Empty string means x86_64 in anyvm
3257+
# Sync VM arch for debug logging later
3258+
debuglog(config['debug'], "Fallback to x86_64 due to missing aarch64 asset")
3259+
target_zst_fallback = "{}-{}.qcow2.zst".format(config['os'], config['release'])
3260+
candidate_url_fallback = "https://github.com/{}/releases/download/{}/{}".format(search_repo, tag, target_zst_fallback)
3261+
debuglog(config['debug'], "Checking fallback x86_64 URL: {}".format(candidate_url_fallback))
3262+
if check_url_exists(candidate_url_fallback, config['debug']):
3263+
debuglog(config['debug'], "Fallback x86_64 URL exists!")
3264+
use_this_builder = True
3265+
found_zst_link = candidate_url_fallback
3266+
else:
3267+
target_xz_fallback = target_zst_fallback.replace('.zst', '.xz')
3268+
candidate_url_xz_fallback = "https://github.com/{}/releases/download/{}/{}".format(search_repo, tag, target_xz_fallback)
3269+
debuglog(config['debug'], "Checking fallback x86_64 URL (xz): {}".format(candidate_url_xz_fallback))
3270+
if check_url_exists(candidate_url_xz_fallback, config['debug']):
3271+
debuglog(config['debug'], "Fallback x86_64 URL (xz) exists!")
3272+
use_this_builder = True
3273+
found_zst_link = candidate_url_xz_fallback
3274+
else:
3275+
debuglog(config['debug'], "Candidate URL not found (including fallback), falling back to full search")
32493276
else:
32503277
debuglog(config['debug'], "Candidate URL not found, falling back to full search")
32513278
else:
@@ -3292,41 +3319,60 @@ def get_releases(repo_slug):
32923319
target_tag = config['builder']
32933320
if not target_tag.startswith('v'):
32943321
target_tag = "v" + target_tag
3322+
3323+
def filter_releases(data, tag):
3324+
return [r for r in data if r.get('tag_name') == tag]
3325+
32953326
debuglog(config['debug'], "Filtering releases for tag: {}".format(target_tag))
3296-
releases_data = [r for r in releases_data if r.get('tag_name') == target_tag]
3327+
filtered = filter_releases(releases_data, target_tag)
3328+
3329+
if not filtered:
3330+
debuglog(config['debug'], "Builder version {} not found in cache. Refreshing...".format(target_tag))
3331+
releases_data = get_releases(builder_repo, force_refresh=True)
3332+
if not releases_data:
3333+
fatal("Unsupported OS: {}. Builder repository {} not found or inaccessible.".format(config['os'], builder_repo))
3334+
filtered = filter_releases(releases_data, target_tag)
3335+
3336+
releases_data = filtered
32973337
if not releases_data:
3298-
fatal("Builder version {} not found in repository {}.".format(target_tag, builder_repo))
3338+
fatal("Builder version {} not found in repository {} even after refresh.".format(target_tag, builder_repo))
32993339
else:
33003340
releases_data = []
33013341

33023342
published_at = ""
33033343
# Find release version if not provided
33043344
if not config['release']:
3305-
for r in releases_data:
3306-
#log(r)
3307-
for asset in r.get('assets', []):
3308-
u = asset.get('browser_download_url', '')
3309-
#log(u)
3310-
if u.endswith("qcow2.zst") or u.endswith("qcow2.xz"):
3311-
if config['arch'] and config['arch'] != "x86_64" and config['arch'] not in u:
3312-
continue
3313-
# Extract version roughly
3314-
filename=u.split('/')[-1]
3315-
filename= removesuffix(filename, ".qcow2.zst")
3316-
filename= removesuffix(filename, ".qcow2.xz")
3317-
parts = filename.split('-')
3318-
if len(parts) > 1:
3319-
ver = parts[1]
3320-
debuglog(config['debug'], "Candidate release found: {} from asset {}".format(ver, filename))
3321-
if published_at and published_at > r.get('published_at', ''):
3345+
def find_latest_release(data, arch):
3346+
p_at = ""
3347+
found_v = ""
3348+
for r in data:
3349+
for asset in r.get('assets', []):
3350+
u = asset.get('browser_download_url', '')
3351+
if u.endswith("qcow2.zst") or u.endswith("qcow2.xz"):
3352+
if arch and arch != "x86_64" and arch not in u:
33223353
continue
3323-
if not published_at:
3324-
published_at = r.get('published_at', '')
3325-
config['release'] = ver
3326-
elif cmp_version(ver, config['release']) > 0:
3327-
published_at = r.get('published_at', '')
3328-
config['release'] = ver
3329-
debuglog(config['debug'],"Updated latest release to: " + config['release'])
3354+
filename=u.split('/')[-1]
3355+
filename= removesuffix(filename, ".qcow2.zst")
3356+
filename= removesuffix(filename, ".qcow2.xz")
3357+
parts = filename.split('-')
3358+
if len(parts) > 1:
3359+
ver = parts[1]
3360+
debuglog(config['debug'], "Candidate release found: {} from asset {}".format(ver, filename))
3361+
if p_at and p_at > r.get('published_at', ''):
3362+
continue
3363+
if not p_at or cmp_version(ver, found_v) > 0:
3364+
p_at = r.get('published_at', '')
3365+
found_v = ver
3366+
return found_v, p_at
3367+
3368+
config['release'], published_at = find_latest_release(releases_data, config['arch'])
3369+
3370+
if not config['release'] and config['arch'] == "aarch64" and not arch_specified:
3371+
debuglog(config['debug'], "No aarch64 release found, searching for x86_64 fallback release...")
3372+
config['release'], published_at = find_latest_release(releases_data, "")
3373+
if config['release']:
3374+
log("No aarch64 release found for {}. Falling back to x86_64.".format(config['os']))
3375+
config['arch'] = ""
33303376

33313377

33323378
log("Using release: " + config['release'])
@@ -3360,6 +3406,26 @@ def find_image_link(releases, target_zst, target_xz):
33603406
releases_data = repo_releases
33613407
zst_link = link
33623408
break
3409+
3410+
# If still no link and we are on aarch64 and it wasn't specified, fallback to x86_64 full search
3411+
if not zst_link and config['arch'] == "aarch64" and not arch_specified:
3412+
log("No aarch64 image found in any repository. Trying x86_64 fallback search...")
3413+
config['arch'] = "" # x86_64
3414+
target_zst_fallback = "{}-{}.qcow2.zst".format(config['os'], config['release'])
3415+
target_xz_fallback = "{}-{}.qcow2.xz".format(config['os'], config['release'])
3416+
3417+
searched = set()
3418+
for repo in search_repos:
3419+
if repo in searched:
3420+
continue
3421+
searched.add(repo)
3422+
repo_releases = releases_data if repo == builder_repo else get_releases(repo)
3423+
link = find_image_link(repo_releases, target_zst_fallback, target_xz_fallback)
3424+
if link:
3425+
builder_repo = repo
3426+
releases_data = repo_releases
3427+
zst_link = link
3428+
break
33633429

33643430
if not zst_link:
33653431
fatal("Cannot find the image link.")

0 commit comments

Comments
 (0)