import os
import subprocess
class PackageManagerError(Exception):
def __init__(self, err):
self.returncode = err.returncode
self.stdout = err.stdout.decode()
self.stderr = err.stderr.decode()
class PackageManager(object):
binary = None
kernel_name = None
kernel_dev_name = None
list_installed_cmd = None
_kernel_ver = None
@property
def kernel_ver(self):
if not self._kernel_ver:
self._kernel_ver = self._exec('uname', '-r').strip()
return self._kernel_ver
@property
def kernel_name_full(self):
return '-'.join([self.kernel_name, self.kernel_ver])
@property
def kernel_dev_name_full(self):
return '-'.join([self.kernel_dev_name, self.kernel_ver])
def _exec(self, *args):
try:
process = subprocess.run(args, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, check=True)
except subprocess.CalledProcessError as err:
raise PackageManagerError(err)
return process.stdout.decode()
def install(self, *args):
return self._exec(self.binary, 'install', '-y', *args)
def install_kernel_dev(self, *args):
return self.install(self.kernel_dev_name_full, *args)
def is_package_installed(self, package):
try:
self._exec(*self.list_installed_cmd, package)
except PackageManagerError:
return False
return True
def is_kernel_dev_installed(self):
return self.is_package_installed(self.kernel_dev_name_full)
_registry = []
def register(cls):
if issubclass(cls, PackageManager) and cls is not PackageManager:
_registry.append(cls)
return cls
def detect():
for provider in _registry:
if os.path.exists(provider.binary):
return provider()
raise OSError("Can't detect package manager")
@register
class Deb(PackageManager):
binary = '/usr/bin/apt-get'
kernel_name = 'linux-image'
kernel_dev_name = 'linux-headers'
list_installed_cmd = '/usr/bin/dpkg', '--list'
@register
class Rpm(PackageManager):
binary = '/usr/bin/yum'
kernel_name = 'kernel'
kernel_plus_name = 'kernel-plus'
kernel_dev_name = '{}-devel'
list_installed_cmd = '/usr/bin/yum', 'list', 'installed'
def __init__(self):
if 'plus' in self.kernel_ver and \
self.is_package_installed(self.kernel_plus_name):
self.kernel_name = self.kernel_plus_name
self.kernel_dev_name = self.kernel_dev_name.format(self.kernel_name)