Skip to content

Commit

Permalink
qvm-template: {reinstall,{up,down}grade}: Better handling and checks …
Browse files Browse the repository at this point in the history
…for existing version.
  • Loading branch information
WillyPillow committed Jul 30, 2020
1 parent 90e4f65 commit 3ada7af
Showing 1 changed file with 50 additions and 15 deletions.
65 changes: 50 additions & 15 deletions qubesadmin/tools/qvm_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ def parse_config(path):
return dict(line.rstrip('\n').split('=', 1) for line in fd)

def install(args, app, version_selector=VersionSelector.LATEST,
ignore_existing=False):
override_existing=False):
try:
with open(LOCK_FILE, 'x') as _:
pass
Expand All @@ -172,11 +172,9 @@ def install(args, app, version_selector=VersionSelector.LATEST,
dl_list = get_dl_list(args, app, version_selector=version_selector)
dl_list_copy = dl_list.copy()
# Verify that the templates are not yet installed
# TODO: Check that installed versions satisfy
# the {reinstall,{up,down}grade} requirements
for name, (ver, dlsize, reponame) in dl_list.items():
assert reponame != '@commandline'
if not ignore_existing and name in app.domains:
if not override_existing and name in app.domains:
print(('Template \'%s\' already installed, skipping...'
' (You may want to use the {reinstall,upgrade,downgrade}'
' operations.)') % name, file=sys.stderr)
Expand Down Expand Up @@ -214,12 +212,45 @@ def install(args, app, version_selector=VersionSelector.LATEST,
name = package_name[len(PACKAGE_NAME_PREFIX):]

# Another check for already-downloaded RPMs
if not ignore_existing and name in app.domains:
if not override_existing and name in app.domains:
print(('Template \'%s\' already installed, skipping...'
' (You may want to use the'
' {reinstall,upgrade,downgrade}'
' operations.)') % name, file=sys.stderr)
continue
# Check if local versus candidate version is in line with the
# operation
elif override_existing:
if name not in app.domains:
parser.error(
"Template '%s' not already installed." % name)
vm = app.domains[name]
pkg_evr = (
str(package_hdr[rpm.RPMTAG_EPOCHNUM]),
package_hdr[rpm.RPMTAG_VERSION],
package_hdr[rpm.RPMTAG_RELEASE])
vm_evr = (
vm.features['template-epoch'],
vm.features['template-version'],
vm.features['template-release'])
cmp_res = rpm.labelCompare(pkg_evr, vm_evr)
if version_selector == VersionSelector.REINSTALL \
and cmp_res != 0:
parser.error(
'Same version of template \'%s\' not found.' \
% name)
elif version_selector == VersionSelector.LATEST_LOWER \
and cmp_res != -1:
print(("Template '%s' of lower version"
" already installed, skipping..." % name),
file=sys.stderr)
continue
elif version_selector == VersionSelector.LATEST_HIGHER \
and cmp_res != 1:
print(("Template '%s' of higher version"
" already installed, skipping..." % name),
file=sys.stderr)
continue

print('Installing template \'%s\'...' % name, file=sys.stderr)
extract_rpm(name, rpmfile, target)
Expand Down Expand Up @@ -278,7 +309,6 @@ def qrexec_popen(args, app, service, stdout=subprocess.PIPE, filter_esc=True):
stderr=subprocess.PIPE)

def qrexec_payload(args, app, spec, refresh):
# TODO: Support for force-refresh
_ = app # unused

def check_newline(string, name):
Expand Down Expand Up @@ -657,7 +687,7 @@ def get_dl_list(args, app, version_selector=VersionSelector.LATEST):
candid[name] = (ver, dlsize, reponame)
elif version_selector == VersionSelector.REINSTALL:
if name not in app.domains:
parser.error("Template '%s' not installed." % name)
parser.error("Template '%s' not already installed." % name)
vm = app.domains[name]
cur_ver = (
vm.features['template-epoch'],
Expand All @@ -668,7 +698,7 @@ def get_dl_list(args, app, version_selector=VersionSelector.LATEST):
elif version_selector in [VersionSelector.LATEST_LOWER,
VersionSelector.LATEST_HIGHER]:
if name not in app.domains:
parser.error("Template '%s' not installed." % name)
parser.error("Template '%s' not already installed." % name)
vm = app.domains[name]
cur_ver = (
vm.features['template-epoch'],
Expand All @@ -682,18 +712,23 @@ def get_dl_list(args, app, version_selector=VersionSelector.LATEST):
or rpm.labelCompare(candid[name][0], ver) < 0:
candid[name] = (ver, dlsize, reponame)

# XXX: As it's possible to include version information in `template`
# Perhaps the messages can be improved
if len(candid) == 0:
if version_selector == VersionSelector.LATEST:
parser.error('Template \'%s\' not found.' % template)
elif version_selector == VersionSelector.REINSTALL:
parser.error('Same version of template \'%s\' not found.' \
% template)
# Copy behavior of DNF and do nothing if version not found
elif version_selector == VersionSelector.LATEST_LOWER:
parser.error('Lower version of template \'%s\' not found.' \
% template)
print(("Template '%s' of lowest version"
" already installed, skipping..." % template),
file=sys.stderr)
elif version_selector == VersionSelector.LATEST_HIGHER:
parser.error('Higher version of template \'%s\' not found.' \
% template)
print(("Template '%s' of highest version"
" already installed, skipping..." % template),
file=sys.stderr)

# Merge & choose the template with the highest version
for name, (ver, dlsize, reponame) in candid.items():
Expand Down Expand Up @@ -774,13 +809,13 @@ def main(args=None, app=None):
install(args, app)
elif args.operation == 'reinstall':
install(args, app, version_selector=VersionSelector.REINSTALL,
ignore_existing=True)
override_existing=True)
elif args.operation == 'downgrade':
install(args, app, version_selector=VersionSelector.LATEST_LOWER,
ignore_existing=True)
override_existing=True)
elif args.operation == 'upgrade':
install(args, app, version_selector=VersionSelector.LATEST_HIGHER,
ignore_existing=True)
override_existing=True)
elif args.operation == 'list':
list_templates(args, app, 'list')
elif args.operation == 'info':
Expand Down

0 comments on commit 3ada7af

Please sign in to comment.