Project

General

Profile

Download (10.1 KB) Statistics
| Branch: | Tag: | Revision:
import six
import logging

from itertools import chain
from gettext import gettext as _
from optparse import OptionParser

from yum import YumBase
from yum.plugins import TYPE_CORE, TYPE_INTERACTIVE
from yum.Errors import InstallError
from yum import constants
from yum import updateinfo


log = logging.getLogger(__name__)
logfile = logging.getLogger('yum.filelogging')


class Pattern(object):
"""
Package matching pattern.

Attributes:
name (str): Name.
epoch (str): Epoch.
version (str): Version.
release (str): Release.
arch (str) Arch..
"""

__slots__ = (
'name',
'epoch',
'version',
'release',
'arch',
)

def __init__(self, name, epoch='*', version='*', release='*', arch='*'):
"""
NEVRA

Args:
name (str): Name.
epoch (str): Epoch.
version (str): Version.
release (str): Release.
arch (str) Arch.
"""
self.name = name
self.epoch = epoch
self.version = version
self.release = release
self.arch = arch

def __str__(self):
fmt = '{epoch}:{name}-{version}-{release}.{arch}'
return fmt.format(
epoch=self.epoch,
name=self.name,
version=self.version,
release=self.release,
arch=self.arch)


class TransactionReport(object):
"""
YUM transaction report.
"""

def __init__(self, ts_info, states):
"""
Args:
ts_info: A YUM transaction.
states: List of package states to be included.
"""
self.deps = []
self.resolved = []
self.failed = []
for t in ts_info:
if t.output_state not in states:
continue
qname = str(t.po)
package = dict(
qname=qname,
repoid=t.repoid,
name=t.po.name,
version=t.po.ver,
release=t.po.rel,
arch=t.po.arch,
epoch=t.po.epoch)
if t.output_state == constants.TS_FAILED:
self.failed.append(package)
if t.isDep:
self.deps.append(package)
else:
self.resolved.append(package)

def dict(self):
"""
Dictionary representation.

Returns:
dict: self
"""
return {
'resolved': self.resolved,
'failed': self.failed,
'deps': self.deps,
}

def log(self, heading):
"""
Log the report.

Args:
heading (str): Log entry heading.
"""
if not self:
return
for qname in [p['qname'] for p in chain(self.resolved, self.deps)]:
entry = heading.format(qname)
logfile.info(entry)
log.info(entry)

def __len__(self):
return len(self.resolved) + len(self.deps)


class InstallTxReport(TransactionReport):
"""
Install transaction report.
"""

HEADING = _('Installed: {}')

STATES = (
constants.TS_FAILED,
constants.TS_INSTALL,
constants.TS_TRUEINSTALL,
constants.TS_UPDATE
)

def __init__(self, ts_info, states=STATES):
"""
Args:
ts_info: A YUM transaction.
states: List of package states to be included.
"""
super(InstallTxReport, self).__init__(ts_info, states)

def log(self, heading=HEADING):
"""
Log the report.

Args:
heading (str): Log entry heading.
"""
super(InstallTxReport, self).log(heading)


class UpdateTxReport(TransactionReport):
"""
Update transaction report.
"""

HEADING = _('Updated: {}')

STATES = (
constants.TS_FAILED,
constants.TS_INSTALL,
constants.TS_TRUEINSTALL,
constants.TS_UPDATE
)

def __init__(self, ts_info, states=STATES):
"""
Args:
ts_info: A YUM transaction.
states: List of package states to be included.
"""
super(UpdateTxReport, self).__init__(ts_info, states)

def log(self, heading=HEADING):
"""
Log the report.

Args:
heading (str): Log entry heading.
"""
super(UpdateTxReport, self).log(heading)


class EraseTxReport(TransactionReport):
"""
Erase transaction report.
"""

HEADING = _('Erased: {}')

STATES = (
constants.TS_FAILED,
constants.TS_ERASE
)

def __init__(self, ts_info, states=STATES):
"""
Args:
ts_info: A YUM transaction.
states: List of package states to be included.
"""
super(EraseTxReport, self).__init__(ts_info, states)

def log(self, heading=HEADING):
"""
Log the report.

Args:
heading (str): Log entry heading.
"""
super(EraseTxReport, self).log(heading)


class API(object):
"""
Abstract package management API.

Attributes:
commit (bool): Commit the transaction.
"""

def __init__(self, commit=True):
"""
Args:
commit (bool): Commit the transaction.
Use False for a "dry run".
"""
self.commit = commit


class Package(API):
"""
The package management API.
"""

def install(self, patterns):
"""
Install packages.

Args:
patterns (collections.Iterable): A list of Pattern.

Returns:
dict: A dictionary representation of a TransactionReport.
"""
with LibYum() as lib:
for pattern in patterns:
try:
lib.install(pattern=str(pattern))
except InstallError as caught:
description = six.text_type(caught).encode('utf-8')
caught.value = '%s: %s' % (pattern, description)
raise caught
lib.resolveDeps()
if self.commit and len(lib.tsInfo):
lib.processTransaction()
report = InstallTxReport(lib.tsInfo)
if self.commit:
report.log()
return report.dict()

def update(self, patterns=(), advisories=()):
"""
Update packages.

Args:
patterns (collections.Iterable): A list of Pattern.
advisories (collections.Iterable): A list of advisory IDs.

Returns:
dict: A dictionary representation of a TransactionReport.
"""
with LibYum() as lib:
if advisories:
lib.updateinfo_filters = {
'bzs': [],
'bugfix': None,
'sevs': [],
'security': None,
'advs': advisories,
'cves': []
}
updateinfo.update_minimal(lib)
else:
if patterns:
for pattern in patterns:
lib.update(pattern=str(pattern))
else:
lib.update()
lib.resolveDeps()
if self.commit and len(lib.tsInfo):
lib.processTransaction()
report = UpdateTxReport(lib.tsInfo)
if self.commit:
report.log()
return report.dict()

def uninstall(self, patterns):
"""
Uninstall (remove) packages.

Args:
patterns (collections.Iterable): A list of Pattern.

Returns:
dict: A dictionary representation of a TransactionReport.
"""
with LibYum() as lib:
for pattern in patterns:
lib.remove(pattern=str(pattern))
lib.resolveDeps()
if self.commit and len(lib.tsInfo):
lib.processTransaction()
report = EraseTxReport(lib.tsInfo)
if self.commit:
report.log()
return report.dict()


class PackageGroup(API):
"""
Package group management API.
"""

def install(self, names):
"""
Install package groups.

Args:
names (collections.Iterable): A list of group names.

Returns:
dict: A dictionary representation of a TransactionReport.
"""
with LibYum() as lib:
for name in names:
lib.selectGroup(name)
lib.resolveDeps()
if self.commit and len(lib.tsInfo):
lib.processTransaction()
report = InstallTxReport(lib.tsInfo)
if self.commit:
report.log()
return report.dict()

def uninstall(self, names):
"""
Uninstall package groups.

Args:
names (collections.Iterable): A list of group names.

Returns:
dict: A dictionary representation of a TransactionReport.
"""
with LibYum() as lib:
for name in names:
lib.groupRemove(name)
lib.resolveDeps()
if self.commit and len(lib.tsInfo):
lib.processTransaction()
report = EraseTxReport(lib.tsInfo)
if self.commit:
report.log()
return report.dict()


class LibYum(YumBase):
"""
A YUM base.
"""

def __init__(self):
"""
Initialization.
"""
parser = OptionParser()
parser.parse_args([])
self.__parser = parser
super(LibYum, self).__init__()
self.preconf.optparser = self.__parser
self.preconf.plugin_types = (TYPE_CORE, TYPE_INTERACTIVE)
self.conf.assumeyes = True

def doPluginSetup(self, *args, **kwargs):
"""
Plugin setup.

Args:
*args:
**kwargs:
"""
super(LibYum, self).doPluginSetup(*args, **kwargs)
p = self.__parser
options, args = p.parse_args([])
self.plugins.setCmdLine(options, args)

def __enter__(self):
return self

def __exit__(self, *unused):
self.close()
(5-5/7)