in src/core/src/package_managers/AptitudePackageManager.py [0:0]
def is_package_version_installed(self, package_name, package_version):
""" Returns true if the specific package version is installed """
self.composite_logger.log_verbose("\nCHECKING PACKAGE INSTALL STATUS FOR: " + str(package_name) + " (" + str(package_version) + ")")
# DEFAULT METHOD
self.composite_logger.log_verbose(" - [1/2] Verifying install status with Dpkg.")
cmd = self.cmd_single_package_find_install_dpkg_template.replace('<PACKAGE-NAME>', package_name)
code, output = self.env_layer.run_command_output(cmd, False, False)
lines = output.strip().split('\n')
if code == 1: # usually not found
# Sample output format ------------------------------------------
# dpkg-query: package 'mysql-client' is not installed and no information is available
# Use dpkg --info (= dpkg-deb --info) to examine archive files,
# and dpkg --contents (= dpkg-deb --contents) to list their contents.
# ------------------------------------------ -------------------
self.composite_logger.log_verbose(" - Return code: 1. The package is likely NOT present on the system.")
for line in lines:
if 'not installed' in line and package_name in line:
self.composite_logger.log_verbose(" - Discovered to be not installed: " + str(line))
return False
else:
self.composite_logger.log_verbose(" - Inapplicable line: " + str(line))
self.telemetry_writer.write_event("[Installed check] Return code: 1. Unable to verify package not present on the system: " + str(output), Constants.TelemetryEventLevel.Verbose)
elif code == 0: # likely found
# Sample output format ------------------------------------------
# Package: mysql-server
# Status: install ok installed
# Priority: optional
# Section: database
# Installed-Size: 107
# Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
# Architecture: all
# Source: mysql-5.7
# Version: 5.7.25-0ubuntu0.16.04.2
# Depends: mysql-server-5.7
# ------------------------------------------ --------------------
self.composite_logger.log_verbose(" - Return code: 0. The package is likely present on the system.")
composite_found_flag = 0
for line in lines:
if 'Package: ' in line:
if package_name in line:
composite_found_flag = composite_found_flag | 1
else: # should never hit for the way this is invoked, hence telemetry
self.composite_logger.log_verbose(" - Did not match name: " + str(package_name) + " (" + str(line) + ")")
self.telemetry_writer.write_event("[Installed check] Name did not match: " + package_name + " (line=" + str(line) + ")(out=" + str(output) + ")", Constants.TelemetryEventLevel.Verbose)
continue
if 'Version: ' in line:
if package_version in line:
composite_found_flag = composite_found_flag | 2
else: # should never hit for the way this is invoked, hence telemetry
self.composite_logger.log_verbose(" - Did not match version: " + str(package_version) + " (" + str(line) + ")")
self.telemetry_writer.write_event("[Installed check] Version did not match: " + str(package_version) + " (line=" + str(line) + ")(out=" + str(output) + ")", Constants.TelemetryEventLevel.Verbose)
continue
if 'Status: ' in line:
if 'install ok installed' in line:
composite_found_flag = composite_found_flag | 4
else: # should never hit for the way this is invoked, hence telemetry
self.composite_logger.log_verbose(" - Did not match status: " + str(package_name) + " (" + str(line) + ")")
self.telemetry_writer.write_event("[Installed check] Status did not match: 'install ok installed' (line=" + str(line) + ")(out=" + str(output) + ")", Constants.TelemetryEventLevel.Verbose)
continue
if composite_found_flag & 7 == 7: # whenever this becomes true, the exact package version is installed
self.composite_logger.log_verbose(" - Package, Version and Status matched. Package is detected as 'Installed'.")
return True
self.composite_logger.log_verbose(" - Inapplicable line: " + str(line))
self.composite_logger.log_verbose(" - Install status check did NOT find the package installed: (composite_found_flag=" + str(composite_found_flag) + ")")
self.telemetry_writer.write_event("Install status check did NOT find the package installed: (composite_found_flag=" + str(composite_found_flag) + ")(output=" + output + ")", Constants.TelemetryEventLevel.Verbose)
else: # This is not expected to execute. If it does, the details will show up in telemetry. Improve this code with that information.
self.composite_logger.log_debug(" - Unexpected return code from dpkg: " + str(code) + ". Output: " + str(output))
self.telemetry_writer.write_event("Unexpected return code from dpkg: Cmd=" + str(cmd) + ". Code=" + str(code) + ". Output=" + str(output), Constants.TelemetryEventLevel.Verbose)
# SECONDARY METHOD - Fallback
# Sample output format
# Listing... Done
# apt/xenial-updates,now 1.2.29 amd64 [installed]
self.composite_logger.log_verbose(" - [2/2] Verifying install status with Apt.")
cmd = self.cmd_single_package_find_install_apt_template.replace('<PACKAGE-NAME>', package_name)
output = self.invoke_package_manager(cmd)
lines = output.strip().split('\n')
for line in lines:
package_details = line.split(' ')
if len(package_details) < 4:
self.composite_logger.log_verbose(" - Inapplicable line: " + str(line))
else:
self.composite_logger.log_verbose(" - Applicable line: " + str(line))
discovered_package_name = package_details[0].split('/')[0] # index out of bounds check is deliberately not being done
if discovered_package_name != package_name:
self.composite_logger.log_verbose(" - Did not match name: " + discovered_package_name + " (" + package_name + ")")
continue
if package_details[1] != package_version:
self.composite_logger.log_verbose(" - Did not match version: " + package_details[1] + " (" + str(package_details[1]) + ")")
continue
if 'installed' not in package_details[3]:
self.composite_logger.log_verbose(" - Did not find status: " + str(package_details[3] + " (" + str(package_details[3]) + ")"))
continue
self.composite_logger.log_verbose(" - Package version specified was determined to be installed.")
self.telemetry_writer.write_event("[Installed check] Fallback code disagreed with dpkg.", Constants.TelemetryEventLevel.Verbose)
return True
self.composite_logger.log_verbose(" - Package version specified was determined to NOT be installed.")
return False