summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichal Minar <miminar@redhat.com>2012-10-06 21:51:43 +0200
committerMichal Minar <miminar@redhat.com>2012-10-06 21:51:43 +0200
commit1ae172139edb7648b3729b6459b9f9a6c02212b4 (patch)
tree001c30285621802c01040d6269a709dc4709489a /src
parent4ef9ef7772d2f06f924ab6c6d23f727aa36a825a (diff)
downloadopenlmi-providers-1ae172139edb7648b3729b6459b9f9a6c02212b4.tar.gz
openlmi-providers-1ae172139edb7648b3729b6459b9f9a6c02212b4.tar.xz
openlmi-providers-1ae172139edb7648b3729b6459b9f9a6c02212b4.zip
tests rewritten to pywhon scripts
currently testing data are suitable only for Fedora 17 added README for tests lot of bug fixes support for Remove method in LMI_YumPackage provider
Diffstat (limited to 'src')
-rw-r--r--src/yum/providers/LMI_YumFileCheck.py3
-rw-r--r--src/yum/providers/LMI_YumInstalledPackage.py47
-rw-r--r--src/yum/providers/LMI_YumPackage.py200
-rw-r--r--src/yum/providers/LMI_YumPackageFile.py4
-rw-r--r--src/yum/providers/util/common.py112
-rw-r--r--src/yum/test/README5
-rw-r--r--src/yum/test/common.py109
-rw-r--r--src/yum/test/test_common.sh91
-rwxr-xr-xsrc/yum/test/test_yum_file_check.py289
-rwxr-xr-xsrc/yum/test/test_yum_installed_package.py241
-rwxr-xr-xsrc/yum/test/test_yum_package.py79
-rwxr-xr-xsrc/yum/test/yum_package.sh278
12 files changed, 968 insertions, 490 deletions
diff --git a/src/yum/providers/LMI_YumFileCheck.py b/src/yum/providers/LMI_YumFileCheck.py
index 7b11af9..9e6e8d1 100644
--- a/src/yum/providers/LMI_YumFileCheck.py
+++ b/src/yum/providers/LMI_YumFileCheck.py
@@ -212,8 +212,7 @@ class LMI_YumFileCheck(CIMProvider2):
with YumDB.getInstance(env) as yb:
vpkg = YumFileCheck.object_path2yumcheck(env, object_name)
fc = YumFileCheck.test_file(env,
- YumFileCheck.checksumtype_str2pywbem(
- YumFileCheck.pkg_checksum_type(vpkg.po)),
+ YumFileCheck.pkg_checksum_type(vpkg.po),
vpkg._files[object_name["Name"]])
out_params = []
ret = 0 if YumFileCheck.filecheck_passed(fc) else 2
diff --git a/src/yum/providers/LMI_YumInstalledPackage.py b/src/yum/providers/LMI_YumInstalledPackage.py
index 5a20b3c..915ff2b 100644
--- a/src/yum/providers/LMI_YumInstalledPackage.py
+++ b/src/yum/providers/LMI_YumInstalledPackage.py
@@ -25,7 +25,7 @@ Instruments the CIM class LMI_YumInstalledPackage
import itertools
import pywbem
from pywbem.cim_provider2 import CIMProvider2
-from LMI_YumPackage import pkg2model
+from LMI_YumPackage import pkg2model, LMI_YumPackage
from LMI_YumFileCheck import filecheck2model
from util.common import *
@@ -72,7 +72,7 @@ class LMI_YumInstalledPackage(CIMProvider2):
check_computer_system_op(env, model['System'])
with YumDB.getInstance(env):
pkg = YumPackage.object_path2pkg(env, model['Software'])
- model['Software'] = pkg2model(pkg, env, True)
+ model['Software'] = pkg2model(env, pkg, True)
return model
def enum_instances(self, env, model, keys_only):
@@ -113,7 +113,7 @@ class LMI_YumInstalledPackage(CIMProvider2):
model['System'] = get_computer_system_op()
with YumDB.getInstance(env) as yb:
for rpm in yb.rpmdb:
- iname = pkg2model(rpm, env, True, yum_package_path)
+ iname = pkg2model(env, rpm, True, yum_package_path)
model['Software'] = iname
if keys_only:
yield model
@@ -155,10 +155,33 @@ class LMI_YumInstalledPackage(CIMProvider2):
logger = env.get_logger()
logger.log_debug('Entering %s.set_instance()' \
% self.__class__.__name__)
- # TODO create or modify the instance
- # Remove to implement
- raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED)
- return instance
+
+ # parse and check arguments
+ if modify_existing is True:
+ raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND,
+ "MofifyInstance is not supported")
+
+ check_computer_system_op(env, instance['System'])
+
+ with YumDB.getInstance(env) as yb:
+ pkg = YumPackage.object_path2pkg_search(env, instance['Software'])
+ if isinstance(pkg, yum.rpmsack.RPMInstalledPackage):
+ raise pywbem.CIMError(pywbem.CIM_ERR_ALREADY_EXISTS,
+ "Package is already installed.")
+
+ logger.log_info('installing package {}'.format(pkg.nevra))
+ # install
+ yb.install(pkg)
+ yb.buildTransaction()
+ yb.processTransaction()
+ logger.log_info('package installed'.format(pkg.nevra))
+
+ # return instance
+ pkg_iname = pkg2model(env, pkg, True)
+ pkg_iname["SoftwareElementState"] = \
+ LMI_YumPackage.Values.SoftwareElementState.Executable
+ instance["Software"] = pkg_iname
+ return LMI_YumInstalledPackage(env).get_instance(env, instance)
def delete_instance(self, env, instance_name):
"""Delete an instance.
@@ -319,10 +342,7 @@ class LMI_YumInstalledPackage(CIMProvider2):
pkg, pkg.hdr.fiFromHeader(), csum, [], True)
for vpf in vpkg:
fc = YumFileCheck.test_file(env, csum, vpf)
- if ( fc.exists
- and all( v[0] == v[1]
- for v in fc if isinstance(v, tuple))):
- continue
+ if YumFileCheck.filecheck_passed(fc): continue
failed.append(filecheck2model(
vpkg, vpf.filename, env, keys_only=True, fc=fc))
out_params = [ pywbem.CIMParameter('Failed', type='reference',
@@ -415,7 +435,7 @@ class LMI_YumInstalledPackage(CIMProvider2):
'could not find any matching available package')
raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND)
out_params = [pywbem.CIMParameter('Installed', type='reference',
- value=pkg2model(pkg, env, True))]
+ value=pkg2model(env, pkg, True))]
if orig.evra == pkg.evra:
logger.log_info('already up to date')
return (self.Values.Update.Already_newest, out_params)
@@ -430,6 +450,9 @@ class LMI_YumInstalledPackage(CIMProvider2):
logger.log_info('package {} updated to: {}'.format(
orig.name, pkg.evra))
+ out_params[0].value["SoftwareElementState"] = \
+ LMI_YumPackage.Values.SoftwareElementState.Executable
+
return (self.Values.Update.Successful_installation, out_params)
class Values(object):
diff --git a/src/yum/providers/LMI_YumPackage.py b/src/yum/providers/LMI_YumPackage.py
index 427e7fa..3b93c86 100644
--- a/src/yum/providers/LMI_YumPackage.py
+++ b/src/yum/providers/LMI_YumPackage.py
@@ -32,11 +32,11 @@ from util.common import *
pkg2model = YumPackage.pkg2model_wrapper('root/cimv2', "LMI_YumPackage")
class LMI_YumPackage(CIMProvider2):
- """Instrument the CIM class LMI_YumPackage
+ """Instrument the CIM class LMI_YumPackage
RPM package installed on particular computer system with YUM (The
Yellowdog Updated, Modified) package manager.
-
+
"""
def __init__ (self, env):
@@ -49,47 +49,47 @@ class LMI_YumPackage(CIMProvider2):
Keyword arguments:
env -- Provider Environment (pycimmb.ProviderEnvironment)
- model -- A template of the pywbem.CIMInstance to be returned. The
- key properties are set on this instance to correspond to the
+ model -- A template of the pywbem.CIMInstance to be returned. The
+ key properties are set on this instance to correspond to the
instanceName that was requested. The properties of the model
- are already filtered according to the PropertyList from the
+ are already filtered according to the PropertyList from the
request. Only properties present in the model need to be
- given values. If you prefer, you can set all of the
- values, and the instance will be filtered for you.
+ given values. If you prefer, you can set all of the
+ values, and the instance will be filtered for you.
Possible Errors:
CIM_ERR_ACCESS_DENIED
- CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized
+ CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized
or otherwise incorrect parameters)
- CIM_ERR_NOT_FOUND (the CIM Class does exist, but the requested CIM
+ CIM_ERR_NOT_FOUND (the CIM Class does exist, but the requested CIM
Instance does not exist in the specified namespace)
CIM_ERR_FAILED (some other unspecified error occurred)
"""
-
+
logger = env.get_logger()
logger.log_debug('Entering %s.get_instance()' \
% self.__class__.__name__)
with YumDB.getInstance(env):
pkg = YumPackage.object_path2pkg(env, model.path, 'all')
- return pkg2model(pkg, env, keys_only=False, model=model)
+ return pkg2model(env, pkg, keys_only=False, model=model)
def enum_instances(self, env, model, keys_only):
"""Enumerate instances.
The WBEM operations EnumerateInstances and EnumerateInstanceNames
- are both mapped to this method.
+ are both mapped to this method.
This method is a python generator
Keyword arguments:
env -- Provider Environment (pycimmb.ProviderEnvironment)
- model -- A template of the pywbem.CIMInstances to be generated.
- The properties of the model are already filtered according to
- the PropertyList from the request. Only properties present in
- the model need to be given values. If you prefer, you can
- always set all of the values, and the instance will be filtered
- for you.
+ model -- A template of the pywbem.CIMInstances to be generated.
+ The properties of the model are already filtered according to
+ the PropertyList from the request. Only properties present in
+ the model need to be given values. If you prefer, you can
+ always set all of the values, and the instance will be filtered
+ for you.
keys_only -- A boolean. True if only the key properties should be
set on the generated instances.
@@ -101,43 +101,43 @@ class LMI_YumPackage(CIMProvider2):
logger = env.get_logger()
logger.log_debug('Entering %s.enum_instances()' \
% self.__class__.__name__)
-
+
# Prime model.path with knowledge of the keys, so key values on
# the CIMInstanceName (model.path) will automatically be set when
- # we set property values on the model.
+ # we set property values on the model.
model.path.update({'TargetOperatingSystem': None, 'Version': None,
'SoftwareElementState': None, 'Name': None,
'SoftwareElementID': None})
-
+
with YumDB.getInstance(env) as yb:
# get all packages
pl = yb.doPackageLists('all', showdups=True)
pl = itertools.chain(pl.installed, pl.available)
# NOTE: available ∩ installed = ∅
for pkg in sorted(pl, key=lambda a:a.evra):
- yield pkg2model(pkg, env, keys_only, model)
+ yield pkg2model(env, pkg, keys_only, model)
def set_instance(self, env, instance, modify_existing):
"""Return a newly created or modified instance.
Keyword arguments:
env -- Provider Environment (pycimmb.ProviderEnvironment)
- instance -- The new pywbem.CIMInstance. If modifying an existing
- instance, the properties on this instance have been filtered by
+ instance -- The new pywbem.CIMInstance. If modifying an existing
+ instance, the properties on this instance have been filtered by
the PropertyList from the request.
modify_existing -- True if ModifyInstance, False if CreateInstance
- Return the new instance. The keys must be set on the new instance.
+ Return the new instance. The keys must be set on the new instance.
Possible Errors:
CIM_ERR_ACCESS_DENIED
CIM_ERR_NOT_SUPPORTED
- CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized
+ CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized
or otherwise incorrect parameters)
- CIM_ERR_ALREADY_EXISTS (the CIM Instance already exists -- only
+ CIM_ERR_ALREADY_EXISTS (the CIM Instance already exists -- only
valid if modify_existing is False, indicating that the operation
was CreateInstance)
- CIM_ERR_NOT_FOUND (the CIM Instance does not exist -- only valid
+ CIM_ERR_NOT_FOUND (the CIM Instance does not exist -- only valid
if modify_existing is True, indicating that the operation
was ModifyInstance)
CIM_ERR_FAILED (some other unspecified error occurred)
@@ -156,22 +156,22 @@ class LMI_YumPackage(CIMProvider2):
Keyword arguments:
env -- Provider Environment (pycimmb.ProviderEnvironment)
- instance_name -- A pywbem.CIMInstanceName specifying the instance
+ instance_name -- A pywbem.CIMInstanceName specifying the instance
to delete.
Possible Errors:
CIM_ERR_ACCESS_DENIED
CIM_ERR_NOT_SUPPORTED
CIM_ERR_INVALID_NAMESPACE
- CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized
+ CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized
or otherwise incorrect parameters)
- CIM_ERR_INVALID_CLASS (the CIM Class does not exist in the specified
+ CIM_ERR_INVALID_CLASS (the CIM Class does not exist in the specified
namespace)
- CIM_ERR_NOT_FOUND (the CIM Class does exist, but the requested CIM
+ CIM_ERR_NOT_FOUND (the CIM Class does exist, but the requested CIM
Instance does not exist in the specified namespace)
CIM_ERR_FAILED (some other unspecified error occurred)
- """
+ """
logger = env.get_logger()
logger.log_debug('Entering %s.delete_instance()' \
@@ -185,11 +185,11 @@ class LMI_YumPackage(CIMProvider2):
"""Implements LMI_YumPackage.Install()
Will install available package.
-
+
Keyword arguments:
env -- Provider Environment (pycimmb.ProviderEnvironment)
- object_name -- A pywbem.CIMInstanceName or pywbem.CIMCLassName
- specifying the object on which the method Update()
+ object_name -- A pywbem.CIMInstanceName or pywbem.CIMCLassName
+ specifying the object on which the method Update()
should be invoked.
Returns a two-tuple containing the return value (type pywbem.Uint32 self.Values.Install)
@@ -197,17 +197,17 @@ class LMI_YumPackage(CIMProvider2):
Output parameters:
Installed -- (type REF (pywbem.CIMInstanceName(
- classname='LMI_YumInstalledPackage', ...))
+ classname='LMI_YumInstalledPackage', ...))
The reference to newly installed package, if installation was
successful. Null otherwise.
Possible Errors:
CIM_ERR_ACCESS_DENIED
- CIM_ERR_INVALID_PARAMETER (including missing, duplicate,
+ CIM_ERR_INVALID_PARAMETER (including missing, duplicate,
unrecognized or otherwise incorrect parameters)
- CIM_ERR_NOT_FOUND (the target CIM Class or instance does not
+ CIM_ERR_NOT_FOUND (the target CIM Class or instance does not
exist in the specified namespace)
- CIM_ERR_METHOD_NOT_AVAILABLE (the CIM Server is unable to honor
+ CIM_ERR_METHOD_NOT_AVAILABLE (the CIM Server is unable to honor
the invocation request)
CIM_ERR_FAILED (some other unspecified error occurred)
@@ -216,58 +216,13 @@ class LMI_YumPackage(CIMProvider2):
logger.log_debug('Entering %s.cim_method_install()' \
% self.__class__.__name__)
- # parse and check arguments
- match_props = {} # args for match_pkg
- if object_name['SoftwareElementID']:
- m = re_nevra.match(object_name['SoftwareElementID'])
- if not m:
- raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER,
- "SoftwareElementID could not be parsed.")
- match_props['nevra'] = object_name['SoftwareElementID']
- match_props['name'] = m.group('name')
- else:
- for matchattr, instattr in (
- ('name', 'name'), ('epoch', 'epoch'), ('version', 'ver'),
- ('release', 'rel'), ('arch', 'arch')):
- if object_name.get(matchattr, None):
- match_props[matchattr] = object_name[matchattr]
-
- if not match_props:
- raise pywbem.CIMError(pywbem.CIM_ERR_FAILED,
- "Too few key values given (give at least a Name).")
- if not 'name' in match_props and not 'nevra' in match_props:
- raise pywbem.CIMError(pywbem.CIM_ERR_FAILED,
- "Missing either Name or SoftwareElementID property.")
-
with YumDB.getInstance(env) as yb:
# get available packages
- pl = yb.doPackageLists('all', showdups=True)
- exact,_,_ = yum.packages.parsePackages(
- itertools.chain(pl.available, pl.installed),
- [match_props['name']])
- exact = yum.misc.unique(exact)
- exact_orig = exact
- exact = sorted( [ p for p in exact if match_pkg(p, **match_props) ]
- , key=lambda a: a.evra)
- if len(exact) == 0:
- logger.log_error('could not find any package for query: {}'
- ' in list: {}'
- .format(match_props, [p.nevra for p in exact_orig]))
- raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND,
- "No matching package found.")
+ pkg = YumPackage.object_path2pkg_search(env, object_name)
out_params = [ pywbem.CIMParameter('Installed', type='reference') ]
- for pkg in exact: # check, whether package is already installed
- if yb.rpmdb.installed(po=pkg):
- out_params[0].value = pkg2model(pkg, env, True)
- return (self.Values.Install.Already_installed, out_params)
- if len(exact) > 1: # should not happen
- logger.log_info('found multiple matching packages'
- ' for query: {}'.format(match_props))
- pkg = exact[-1] # select highest version
- else:
- logger.log_debug('exact match found for query: {}'
- .format(match_props))
- pkg = exact[0]
+ if isinstance(pkg, yum.rpmsack.RPMInstalledPackage):
+ out_params[0].value = pkg2model(env, pkg, True)
+ return (self.Values.Install.Already_installed, out_params)
logger.log_info('installing package {}'.format(pkg.nevra))
# install
@@ -277,9 +232,59 @@ class LMI_YumPackage(CIMProvider2):
logger.log_info('package installed'.format(pkg.nevra))
# return object_name
- out_params[0].value = pkg2model(pkg, env, True, object_name)
+ out_params[0].value = pkg2model(env, pkg, True, object_name)
+ # pkg's class is YumAvailablePackage and pkg2model thinks it's
+ # not installed
+ out_params[0].value['SoftwareElementState'] = \
+ self.Values.SoftwareElementState.Executable
return (self.Values.Install.Successful_installation, out_params)
+ def cim_method_remove(self, env, object_name):
+ """Implements LMI_YumPackage.Remove()
+
+ Will uninstall installed package.
+
+ Keyword arguments:
+ env -- Provider Environment (pycimmb.ProviderEnvironment)
+ object_name -- A pywbem.CIMInstanceName or pywbem.CIMCLassName
+ specifying the object on which the method Remove()
+ should be invoked.
+
+ Returns a two-tuple containing the return value (type pywbem.Uint32 self.Values.Remove)
+ and a list of CIMParameter objects representing the output parameters
+
+ Output parameters: none
+
+ Possible Errors:
+ CIM_ERR_ACCESS_DENIED
+ CIM_ERR_INVALID_PARAMETER (including missing, duplicate,
+ unrecognized or otherwise incorrect parameters)
+ CIM_ERR_NOT_FOUND (the target CIM Class or instance does not
+ exist in the specified namespace)
+ CIM_ERR_METHOD_NOT_AVAILABLE (the CIM Server is unable to honor
+ the invocation request)
+ CIM_ERR_FAILED (some other unspecified error occurred)
+
+ """
+
+ logger = env.get_logger()
+ logger.log_debug('Entering %s.cim_method_remove()' \
+ % self.__class__.__name__)
+
+ with YumDB.getInstance(env) as yb:
+ pkg = YumPackage.object_path2pkg(env, object_name, 'all')
+ if isinstance(pkg, yum.rpmsack.RPMInstalledPackage):
+ logger.log_info('removing package "%s"' % pkg.nevra)
+ yb.remove(pkg)
+ yb.buildTransaction()
+ yb.processTransaction()
+ logger.log_info('package "%s" removed' % pkg.nevra)
+ rval = self.Values.Remove.Successful_removal
+ else:
+ rval = self.Values.Remove.Not_installed
+ #rval = # TODO (type pywbem.Uint32 self.Values.Remove)
+ return (rval, [])
+
class Values(object):
class DetailedStatus(object):
Not_Available = pywbem.Uint16(0)
@@ -430,6 +435,11 @@ class LMI_YumPackage(CIMProvider2):
Oracle_Enterprise_Linux_64_bit = pywbem.Uint16(109)
eComStation_32_bitx = pywbem.Uint16(110)
+ class Remove(object):
+ Not_installed = pywbem.Uint32(0)
+ Successful_removal = pywbem.Uint32(1)
+ Failed = pywbem.Uint32(2)
+
class CommunicationStatus(object):
Unknown = pywbem.Uint16(0)
Not_Available = pywbem.Uint16(1)
@@ -504,9 +514,9 @@ class LMI_YumPackage(CIMProvider2):
Failed = pywbem.Uint32(2)
## end of class LMI_YumPackage
-
+
## get_providers() for associating CIM Class Name to python provider class name
-
-def get_providers(env):
- lmi_yumpackage_prov = LMI_YumPackage(env)
- return {'LMI_YumPackage': lmi_yumpackage_prov}
+
+def get_providers(env):
+ lmi_yumpackage_prov = LMI_YumPackage(env)
+ return {'LMI_YumPackage': lmi_yumpackage_prov}
diff --git a/src/yum/providers/LMI_YumPackageFile.py b/src/yum/providers/LMI_YumPackageFile.py
index 14988d3..45df4c3 100644
--- a/src/yum/providers/LMI_YumPackageFile.py
+++ b/src/yum/providers/LMI_YumPackageFile.py
@@ -73,7 +73,7 @@ class LMI_YumPackageFile(CIMProvider2):
vpkg = YumCheckFile.object_path2yumcheck(env, model['Check'])
model['Check'] = filecheck2model(vpkg, model['Check']['Name'],
env, keys_only=True)
- model['Element'] = pkg2model(vpkg.po, env, keys_only=True)
+ model['Element'] = pkg2model(env, vpkg.po, keys_only=True)
return model
def enum_instances(self, env, model, keys_only):
@@ -284,7 +284,7 @@ class LMI_YumPackageFile(CIMProvider2):
vpkg = YumFileCheck.object_path2yumcheck(env, object_name)
model['Element'] = pkg2model(
- vpkg.po, env, keys_only=True)
+ env, vpkg.po, keys_only=True)
yield model
class Values(object):
diff --git a/src/yum/providers/util/common.py b/src/yum/providers/util/common.py
index 16c10ff..0cd5116 100644
--- a/src/yum/providers/util/common.py
+++ b/src/yum/providers/util/common.py
@@ -168,9 +168,6 @@ def check_computer_system_op(env, system):
raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND,
"\"System\" must be a CIMInstanceName")
our_system = get_computer_system_op()
- if system.namespace != our_system.namespace:
- raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND,
- "\"System\" has wrong namespace")
ch = env.get_cimom_handle()
if not ch.is_subclass(system.namespace,
sub=system.classname,
@@ -574,6 +571,8 @@ class YumPackage:
@staticmethod
def object_path2pkg(env, op, package_list='installed'):
"""
+ @param op must contain precise information of package,
+ otherwise a CIM_ERR_NOT_FOUND error is raised
@param package_list one of {'installed', 'all', 'available'}
says, where to look for given package
"""
@@ -630,6 +629,81 @@ class YumPackage:
return pkg
@staticmethod
+ def object_path2pkg_search(env, op):
+ """
+ similar to object_path2pkg, but tries to find best suitable
+ package matching keys
+
+ If any matching package is already installed, it is returned.
+ Otherwise available package with highest version is returned.
+
+ @param op may be object of CIMInstance or CIMInstanceName and
+ must contain at least \"Name\" or \"SoftwareElementID\"
+ @return instance of yum.rpmsack.RPMInstalledPackage in case of
+ installed package, otherwise yum.packages.YumAvailablePackage
+ """
+ logger = env.get_logger()
+ if isinstance(op, pywbem.CIMInstance):
+ def _get_key(k):
+ v = op.properties.get(k, None)
+ if isinstance(v, pywbem.CIMProperty): return v.value
+ if v is not None: return v
+ logger.log_error('missing key "{}" in inst.props'.format(k))
+ return op.path[k] if k in op.path else None
+ elif isinstance(op, pywbem.CIMInstanceName):
+ _get_key = lambda k: op[k] if k in op else None
+ else:
+ raise TypeError("op must be either CIMInstance or CIMInstanceName")
+
+ # parse and check arguments
+ match_props = {} # args for match_pkg
+ if _get_key('SoftwareElementID'):
+ m = re_nevra.match(_get_key('SoftwareElementID'))
+ if not m:
+ raise pywbem.CIMError(pywbem.CIM_ERR_INVALID_PARAMETER,
+ "SoftwareElementID could not be parsed.")
+ match_props['nevra'] = _get_key('SoftwareElementID')
+ match_props['name'] = m.group('name')
+ else:
+ for matchattr, instattr in (
+ ('name', 'name'), ('epoch', 'epoch'), ('version', 'ver'),
+ ('release', 'rel'), ('arch', 'arch')):
+ if _get_key(matchattr):
+ match_props[matchattr] = _get_key(matchattr)
+
+ if not match_props:
+ raise pywbem.CIMError(pywbem.CIM_ERR_FAILED,
+ "Too few key values given (give at least a Name).")
+ if not 'name' in match_props and not 'nevra' in match_props:
+ raise pywbem.CIMError(pywbem.CIM_ERR_FAILED,
+ "Missing either Name or SoftwareElementID property.")
+
+ # get available packages
+ pl = YumDB.getInstance(env).doPackageLists('all', showdups=True)
+ # NOTE: available ∩ installed = ∅
+ exact,_,_ = yum.packages.parsePackages(
+ itertools.chain(pl.available, pl.installed),
+ [match_props['name']])
+ exact = yum.misc.unique(exact)
+ exact_orig = exact
+ exact = sorted( [ p for p in exact if match_pkg(p, **match_props) ]
+ , key=lambda a: a.evra)
+ if len(exact) == 0:
+ logger.log_error('could not find any package for query: {}'
+ ' in list: {}'
+ .format(match_props, [p.nevra for p in exact_orig]))
+ raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND,
+ "No matching package found.")
+ for pkg in exact: # check, whether package is already installed
+ if isinstance(pkg, yum.rpmsack.RPMInstalledPackage):
+ return pkg
+ logger.log_info(('found multiple matching packages'
+ ' for query: {}' if len(exact) > 1 else
+ 'exact match found for query: {}')
+ .format(match_props))
+ return exact[-1] # select highest version
+
+ @staticmethod
def pkg2model_wrapper(namespace, classname):
"""
@return a function that transforms YumAvailablePackage object
@@ -638,7 +712,7 @@ class YumPackage:
tos = pywbem.Uint16(get_target_operating_system()[0])
- def pkg2model(pkg, env, keys_only=True, model=None):
+ def pkg2model(env, pkg, keys_only=True, model=None):
"""
@param model if None, will be filled with data, otherwise
a new instance of CIMInstance or CIMObjectPath is created
@@ -709,13 +783,17 @@ class YumFileCheck:
yum.constants.RPM_CHECKSUM_TYPES.items())
@staticmethod
- def pkg_checksum_type( pkg):
+ def pkg_checksum_type(pkg):
+ """
+ @return integer representation of checksum type
+ """
if not isinstance(pkg, yum.packages.YumAvailablePackage):
raise TypeError("pkg must be an instance of YumAvailablePackage")
if isinstance(pkg, yum.rpmsack.RPMInstalledPackage):
return pkg.hdr[rpm.RPMTAG_FILEDIGESTALGO]
with self: # ensure, that _yum is inited
- return pkg.yumdb_info.checksum_type
+ return YumFileCheck.checksumtype_str2pywbem(
+ pkg.yumdb_info.checksum_type)
@staticmethod
def checksumtype_num2hash(csumt):
@@ -944,17 +1022,31 @@ class YumFileCheck:
def filecheck_passed(fc):
if not isinstance(fc, YumFileCheck.FileCheck):
raise TypeError("fc must be an instance of FileCheck")
- return fc.exists and all(v[0] == v[1]
- for v in fc if isinstance(v, tuple))
+ return ( fc.exists
+ and all( v[0] == v[1]
+ for k, v in fc._asdict().items() if (
+ isinstance(v, tuple)
+ and ( k != "last_modification_time"
+ or fc.file_type[0] == \
+ YumFileCheck.filetype_str2pywbem("file")
+ ))))
@staticmethod
def filecheck_wrapper(namespace, classname):
def _filecheck2model_flags(fc):
flags = []
- for v in fc:
+ for k, v in fc._asdict().items():
if isinstance(v, tuple):
- flags.append(fc.exists and v[0] == v[1])
+ if ( k != "last_modification_time"
+ or fc.file_type[0] == YumFileCheck.filetype_str2pywbem(
+ 'file')):
+ # last_modification_time check is valid only for
+ # regular files
+ flag = fc.exists and v[0] == v[1]
+ else:
+ flag = True
+ flags.append(flag)
elif isinstance(v, bool):
flags.append(v)
return flags
diff --git a/src/yum/test/README b/src/yum/test/README
new file mode 100644
index 0000000..d60d1e8
--- /dev/null
+++ b/src/yum/test/README
@@ -0,0 +1,5 @@
+Tests must be run as root on machine with sfcbd broker with
+test dir as CWD. File common.py contains connection settings and
+also test data.
+This directory should contain all rpm packages, that will take part in testing
+to speed it up. These packages are listed in common.py file.
diff --git a/src/yum/test/common.py b/src/yum/test/common.py
new file mode 100644
index 0000000..0da5695
--- /dev/null
+++ b/src/yum/test/common.py
@@ -0,0 +1,109 @@
+from collections import namedtuple
+import os
+import pywbem
+import re
+import subprocess
+import unittest
+
+SCHEMA="http"
+HOSTNAME="localhost"
+PORT=5988
+USER=''
+PASSWORD=''
+
+Package = namedtuple("Package",
+ "name, epoch, ver, rel, arch, "
+ "updatable, up_epoch, up_ver, up_rel")
+# This is a database of packages used in tests. If you modify this, please
+# ensure, that all corresponding rpm packages are present in test directory.
+packages = [ Package(*args) for args in
+ ( ( "python-xlib-doc", "0", "0.15", "0.6.rc1.fc17", "noarch", False
+ , None, None, None)
+ , ( "slv2", "0", "0.6.6", "8.fc17", "x86_64", True
+ , "0", "0.6.6", "9.fc17")
+ ) ]
+
+pkg_files = (
+ ( "bash-completion-1:2.0-1.fc17.noarch",
+ ( "/usr/share/bash-completion/completions/vgs" # symlink
+ , "/usr/share/doc/bash-completion-2.0/README" # file
+ , "/usr/share/doc/bash-completion-2.0" # directory
+ )
+ , )
+ , )
+
+re_nevra = re.compile(r'^(?P<name>.+)-(?P<evra>(?P<epoch>\d+):(?P<ver>[^-]+)'
+ r'-(?P<rel>.+)\.(?P<arch>[^.]+))$')
+
+def make_nevra(name, epoch, ver, rel, arch, with_epoch='NOT_ZERO'):
+ """
+ @param with_epoch may be one of:
+ "NOT_ZERO" - include epoch only if it's not zero
+ "ALWAYS" - include epoch always
+ "NEVER" - do not include epoch at all
+ """
+ estr = ''
+ if with_epoch.lower() == "always":
+ estr = epoch
+ elif with_epoch.lower() == "not_zero":
+ if epoch != "0":
+ estr = epoch
+ if len(estr): estr += ":"
+ return "%s-%s%s-%s.%s" % (name, estr, ver, rel, arch)
+
+def remove_pkg(name, *args):
+ subprocess.call(["rpm", "--quiet"] + list(args) + ["-e", name])
+
+def install_pkg(*args, **kwargs):
+ if len(args) > 1 or len(kwargs) > 0:
+ if kwargs.has_key('nevra'):
+ m = re_nevra.match(kwargs['nevra'])
+ args = [ m.group(k) for k in (
+ 'name', 'epoch', 'ver', 'rel', 'arch') ]
+ nevra = make_nevra(*args, with_epoch="NEVER")
+ rpm_name = nevra + ".rpm"
+ if os.path.exists(rpm_name):
+ subprocess.call(["rpm", "--quiet", "-i", rpm_name])
+ return
+ subprocess.call(["yum", "-q", "-y", "install", args[0]])
+
+def is_installed(*args, **kwargs):
+ if len(args) == 1:
+ return subprocess.call(["rpm", "--quiet", "-q", args[0]]) == 0
+ else:
+ if kwargs.has_key("nevra"):
+ nevra = kwargs["nevra"]
+ name = re_nevra.match(nevra).group('name')
+ else:
+ nevra = make_nevra(*args)
+ name = args[0]
+ try:
+ out = subprocess.check_output(
+ ["rpm", "-q", "--qf", "%{NEVRA}", name])
+ return out == nevra
+ except subprocess.CalledProcessError:
+ return False
+
+def verify_pkg(name):
+ return subprocess.call(["rpm", "--quiet", "-Va", name]) == 0
+
+class YumBaseTestCase(unittest.TestCase):
+
+ def setUp(self):
+ unittest.TestCase.setUp(self)
+ self.url = "%s://%s:%d" % (SCHEMA, HOSTNAME, PORT)
+ self.conn = pywbem.WBEMConnection(self.url, (USER, PASSWORD))
+ self.op = pywbem.CIMInstanceName(
+ namespace="root/cimv2", classname=self.CLASS_NAME)
+
+ def tearDown(self):
+ del self.conn
+
+ def assertIsSubclass(self, cls, base_cls):
+ if not isinstance(cls, basestring):
+ raise TypeError("cls must be a string")
+ if not isinstance(base_cls, basestring):
+ raise TypeError("base_cls must be a string")
+ return self.assertTrue(pywbem.is_subclass(self.conn,
+ "root/cimv2", base_cls, cls))
+
diff --git a/src/yum/test/test_common.sh b/src/yum/test/test_common.sh
deleted file mode 100644
index 1e5cd98..0000000
--- a/src/yum/test/test_common.sh
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/bin/bash
-
-if [ -z $CLASS_NAME ]; then
- echo "variable CLASS_NAME must be defined"
- exit 1
-fi
-
-
-url="http://localhost:5988"
-
-fedora_release=`sed 's/Fedora release\s*\([0-9]\+\).*/\1/' \
- /etc/fedora-release`
-
-function make_nevra() {
- # accepts arguments: name, epoch, ver, rel, arch
- # in this order
- printf "%s-%s:%s-%s.%s" $@
-}
-
-function make_op() {
- local class_name keys
- read class_name keys <<< "$@"
- [ -n "$keys" ] && keys=".$keys"
- printf "root/cimv2:$class_name$keys"
-}
-
-computer_system_keys="CreationClassName=\"Linux_ComputerSystem\""
-computer_system_keys+=",Name=$(hostname)"
-computer_system_op=`make_op Linux_ComputerSystem "$computer_system_keys"`
-op=`make_op ${CLASS_NAME}`
-
-function make_rpm_name() {
- local name epoch ver rel arch;
- if [ $# -ge 5 ]; then
- read name epoch ver rel arch <<< "$@"
- else
- read name ver rel arch <<< "$@"
- fi
- [ $# -gt 5 ] && arch=`echo $arch | cut -d \ -f 1`
- if [ -n "$epoch" -a "$epoch" != 0 ]; then
- epoch="${epoch}:"
- else
- epoch=""
- fi
- printf "%s-%s%s-%s.%s.rpm" "$name" "$epoch" "$ver" "$rel" "$arch"
-}
-
-function is_installed() {
- rpm -q "$1" >/dev/null
-}
-
-function is_installed_nevra() {
- local name epoch ver rel arch;
- read name epoch ver rel arch <<< "$@"
-
- rpm -qi name | sed -n 's/^\(Name\|Epoch\|Version\|Release\|Architecture\)\s*:\s*\(.*\)/\1 \2/p' | \
- while read l; do
- read k v <<< "$l"
- read ${k,,} <<< "$v"
- [ $k == "version" ] && [ -z "$epoch" ] && echo "0" # print epoch
- echo $v
- done | set --
- [ $epoch == $2 ] && [ $ver == $3 ] && [ $rel == $4 ] && [ $arch == $5 ]
-}
-
-function install_pkg() {
- if [ $# == 1 ]; then
- sudo yum -y install $1 || exit 1
- else
- local rpm_name=`make_rpm_name "$@"`
- if ! [ -f "$rpm_name" ]; then
- if [ -f "$dir/$rpm_name" ]; then
- rpm_name="$dir/$rpm_name"
- fi
- fi
- if ! [ -e "$rpm_name" ]; then
- sudo yum -y install "$1"
- else
- sudo rpm -i "$rpm_name"
- fi
- fi
-}
-
-function remove() {
- sudo rpm --allmatches -e "$1"
-}
-
-function wbemerr() {
- wbemcli "$@" |& sed 's:<br\s*/\?>:\n:g'
-}
-
diff --git a/src/yum/test/test_yum_file_check.py b/src/yum/test/test_yum_file_check.py
new file mode 100755
index 0000000..82c8650
--- /dev/null
+++ b/src/yum/test/test_yum_file_check.py
@@ -0,0 +1,289 @@
+#!/usr/bin/env python
+
+from common import *
+import hashlib
+import shutil
+import socket
+import stat
+
+re_checksum = re.compile(r'^([0-9a-fA-F]+)\s+.*')
+
+PassedFlags = namedtuple("PassedFlags",
+ "exists, type, size, mode, checksum, dev, ltarget, uid, gid, mtime")
+
+class TestYumInstalledPackage(YumBaseTestCase):
+
+ CLASS_NAME = "LMI_YumFileCheck"
+ KEYS = ( "CheckID", "Name", "SoftwareElementID", "SoftwareElementState"
+ , "TargetOperatingSystem", "Version")
+
+ hash_num2algo = {
+ 1 : hashlib.md5,
+ 2 : hashlib.sha1,
+ 8 : hashlib.sha256,
+ 9 : hashlib.sha384,
+ 10 : hashlib.sha512,
+ 11 : hashlib.sha224
+ }
+
+ hash_num2cmd = {
+ 1 : "md5sum",
+ 2 : "sha1sum",
+ 8 : "sha256sum",
+ 9 : "sha384sum",
+ 10 : "sha512sum",
+ 11 : "sha224sum"
+ }
+
+ hash_num2length = {
+ 1 : 32,
+ 2 : 40,
+ 8 : 64,
+ 9 : 96,
+ 10 : 128,
+ 11 : 56
+ }
+
+ def make_op(self, nevra, filename):
+ op = self.op.copy()
+ m = re_nevra.match(nevra)
+ name, version = [ m.group(k) for k in ("name", "ver") ]
+ op["Name"] = filename
+ op["Version"] = version
+ op["CheckID"] = "%s#%s" % (name, filename)
+ op["SoftwareElementState"] = pywbem.Uint16(2)
+ op["TargetOperatingSystem"] = pywbem.Uint16(36)
+ op["SoftwareElementID"] = nevra
+ return op
+
+ def make_checksum_str(self, csumnum, filename):
+ return re_checksum.match(subprocess.check_output([
+ self.hash_num2cmd[csumnum], filename])).group(1).lower()
+
+ def do_test_symlink(self, op, nevra, f, inst):
+ target = os.readlink(f)
+ stats = os.lstat(f)
+
+ self.assertEqual(inst["FileType"], pywbem.Uint16(3))
+ self.assertEqual(inst["FileUserID"], stats.st_uid)
+ self.assertEqual(inst["FileGroupID"], stats.st_gid)
+ self.assertEqual(inst["FileMode"], stats.st_mode)
+ self.assertEqual(inst["FileSize"], stats.st_size)
+ self.assertEqual(inst["LinkTarget"], target)
+ self.assertEqual(inst["Checksum"],
+ "0"*self.hash_num2length[inst["ChecksumType"]])
+ self.assertEqual(inst["LastModificationTime"],
+ int(stats.st_mtime))
+
+ # modify owner
+ prev_user = inst["FileUserID"]
+ prev_mtime = inst["LastModificationTime"]
+ prev_pflags = PassedFlags(*inst["PassedFlags"])
+ os.lchown(f, stats.st_uid + 1, -1)
+ inst = self.conn.GetInstance(InstanceName=inst.path)
+ self.assertEqual(inst["FileUserID"], inst["ExpectedFileUserID"] + 1)
+ self.assertEqual(inst["FileUserID"], prev_user + 1)
+ self.assertEqual(inst["FileGroupID"], stats.st_gid)
+ cur_pflags = PassedFlags(*inst["PassedFlags"])
+ #self.assertGreater(inst["LastModificationTime"], prev_mtime)
+
+ self.assertTrue(cur_pflags.exists)
+ self.assertTrue(cur_pflags.type)
+ self.assertTrue(cur_pflags.size)
+ self.assertTrue(cur_pflags.mode)
+ self.assertTrue(cur_pflags.checksum)
+ self.assertTrue(cur_pflags.dev)
+ self.assertTrue(cur_pflags.ltarget)
+ self.assertFalse(cur_pflags.uid)
+ self.assertTrue(cur_pflags.gid)
+ self.assertTrue(cur_pflags.mtime)
+
+ # modify link_target
+ os.remove(f)
+ os.symlink("wrong" + "*"*len(inst["ExpectedLinkTarget"]), f)
+ os.lchown(f, inst["ExpectedFileUserID"], inst["ExpectedFileGroupID"])
+
+ inst = self.conn.GetInstance(InstanceName=inst.path)
+ cur_pflags = PassedFlags(*inst["PassedFlags"])
+ self.assertGreater(len(inst["LinkTarget"]),
+ len(inst["ExpectedLinkTarget"]))
+
+ self.assertTrue(cur_pflags.exists)
+ self.assertTrue(cur_pflags.type)
+ self.assertFalse(cur_pflags.size)
+ self.assertTrue(cur_pflags.mode)
+ self.assertTrue(cur_pflags.checksum)
+ self.assertTrue(cur_pflags.dev)
+ self.assertFalse(cur_pflags.ltarget)
+ self.assertTrue(cur_pflags.uid)
+ self.assertTrue(cur_pflags.gid)
+ self.assertTrue(cur_pflags.mtime)
+
+ def do_test_directory(self, op, nevra, f, inst):
+ stats = os.lstat(f)
+
+ self.assertEqual(inst["FileType"], pywbem.Uint16(2))
+ self.assertEqual(inst["FileUserID"], stats.st_uid)
+ self.assertEqual(inst["FileGroupID"], stats.st_gid)
+ self.assertEqual(inst["FileMode"], stats.st_mode)
+ self.assertEqual(inst["FileSize"], stats.st_size)
+ self.assertIs(inst["LinkTarget"], None)
+ self.assertEqual(inst["Checksum"],
+ "0"*self.hash_num2length[inst["ChecksumType"]])
+ self.assertEqual(inst["LastModificationTime"],
+ int(stats.st_mtime))
+
+ def do_test_file(self, op, nevra, f, inst):
+ stats = os.lstat(f)
+
+ self.assertEqual(inst["FileType"], pywbem.Uint16(1))
+ self.assertEqual(inst["FileUserID"], stats.st_uid)
+ self.assertEqual(inst["FileGroupID"], stats.st_gid)
+ self.assertEqual(inst["FileMode"], stats.st_mode)
+ self.assertEqual(inst["FileSize"], stats.st_size)
+ self.assertIs(inst["LinkTarget"], None)
+ csum = self.make_checksum_str(inst['ChecksumType'], f)
+ self.assertEqual(inst["Checksum"].lower(), csum)
+ self.assertEqual(inst["ExpectedLastModificationTime"],
+ inst["LastModificationTime"])
+ self.assertEqual(inst["LastModificationTime"],
+ int(stats.st_mtime))
+
+ # make it longer
+ with open(f, "a+") as fobj:
+ fobj.write("data\n")
+ inst = self.conn.GetInstance(InstanceName=inst.path)
+ cur_pflags = PassedFlags(*inst["PassedFlags"])
+ self.assertGreater(inst["FileSize"], inst["ExpectedFileSize"])
+ self.assertGreater(inst["LastModificationTime"],
+ inst["ExpectedLastModificationTime"])
+
+ self.assertTrue(cur_pflags.exists)
+ self.assertTrue(cur_pflags.type)
+ self.assertFalse(cur_pflags.size)
+ self.assertTrue(cur_pflags.mode)
+ self.assertFalse(cur_pflags.checksum)
+ self.assertTrue(cur_pflags.dev)
+ self.assertTrue(cur_pflags.ltarget)
+ self.assertTrue(cur_pflags.uid)
+ self.assertTrue(cur_pflags.gid)
+ self.assertFalse(cur_pflags.mtime)
+
+ # change file type
+ os.remove(f)
+ os.symlink(f, f)
+ os.lchown(f, inst["ExpectedFileUserID"], inst["ExpectedFileGroupID"])
+ inst = self.conn.GetInstance(InstanceName=inst.path)
+ cur_pflags = PassedFlags(*inst["PassedFlags"])
+ self.assertNotEqual(inst["LinkTarget"], inst["ExpectedLinkTarget"])
+ self.assertNotEqual(inst["FileSize"], inst["ExpectedFileSize"])
+ self.assertGreater(inst["LastModificationTime"],
+ inst["ExpectedLastModificationTime"])
+ self.assertNotEqual(inst["FileType"], inst["ExpectedFileType"])
+ self.assertEqual(inst["FileType"], pywbem.Uint16(3))
+
+ self.assertTrue(cur_pflags.exists)
+ self.assertFalse(cur_pflags.type)
+ self.assertFalse(cur_pflags.size)
+ self.assertFalse(cur_pflags.mode)
+ self.assertFalse(cur_pflags.checksum)
+ self.assertTrue(cur_pflags.dev)
+ self.assertFalse(cur_pflags.ltarget)
+ self.assertTrue(cur_pflags.uid)
+ self.assertTrue(cur_pflags.gid)
+ self.assertFalse(cur_pflags.mtime)
+
+ # remove it
+ os.remove(f)
+ inst = self.conn.GetInstance(InstanceName=inst.path)
+ cur_pflags = PassedFlags(*inst["PassedFlags"])
+ self.assertEqual(inst["LinkTarget"], inst["ExpectedLinkTarget"])
+ self.assertNotEqual(inst["FileSize"], inst["ExpectedFileSize"])
+ self.assertIsNone(inst["LastModificationTime"])
+ self.assertIsNone(inst["FileType"])
+ self.assertIsNone(inst["Checksum"])
+ self.assertIsNone(inst["FileMode"])
+ self.assertIsNone(inst["FileUserID"])
+ self.assertIsNone(inst["FileGroupID"])
+
+ self.assertFalse(cur_pflags.exists)
+ self.assertFalse(cur_pflags.type)
+ self.assertFalse(cur_pflags.size)
+ self.assertFalse(cur_pflags.mode)
+ self.assertFalse(cur_pflags.checksum)
+ self.assertFalse(cur_pflags.dev)
+ self.assertFalse(cur_pflags.ltarget)
+ self.assertFalse(cur_pflags.uid)
+ self.assertFalse(cur_pflags.gid)
+ self.assertFalse(cur_pflags.mtime)
+
+ def test_get_instance(self):
+ for nevra, files in pkg_files:
+ m = re_nevra.match(nevra)
+ name, version = [ m.group(k) for k in ("name", "ver") ]
+ if is_installed(nevra=nevra) and not verify_pkg(name):
+ remove_pkg(name)
+ if not is_installed(name):
+ install_pkg(nevra=nevra)
+ self.assertTrue(is_installed(nevra=nevra))
+ for f in files:
+ op = self.make_op(nevra, f)
+
+ inst = self.conn.GetInstance(InstanceName=op, LocalOnly=False)
+ self.assertIsInstance(inst, pywbem.CIMInstance)
+ self.assertEqual(inst.path, op)
+ for key in self.KEYS:
+ self.assertEqual(inst[key], op[key])
+
+ self.assertTrue(inst["FileExists"])
+ self.assertEqual(len(inst["PassedFlags"]), 10)
+ self.assertTrue(all(f is True for f in inst["PassedFlags"]))
+ for prop in ( "FileType", "FileUserID", "FileGroupID"
+ , "FileMode", "FileSize", "LinkTarget"
+ , "Checksum", "FileModeFlags"):
+ self.assertEqual(inst["Expected"+prop], inst[prop])
+ if os.path.islink(f):
+ self.do_test_symlink(op, nevra, f, inst)
+ elif os.path.isdir(f):
+ self.do_test_directory(op, nevra, f, inst)
+ elif os.path.isfile(f):
+ self.do_test_file(op, nevra, f, inst)
+
+ def test_invoke_method(self):
+ for nevra, files in pkg_files:
+ m = re_nevra.match(nevra)
+ name, version = [ m.group(k) for k in ("name", "ver") ]
+ if is_installed(nevra=nevra) and not verify_pkg(name):
+ remove_pkg(name)
+ if not is_installed(name):
+ install_pkg(nevra=nevra)
+ self.assertTrue(is_installed(nevra=nevra))
+ for f in files:
+ op = self.make_op(nevra, f)
+
+ (rval, oparms) = self.conn.InvokeMethod(
+ MethodName="Invoke",
+ ObjectName=op)
+ self.assertEqual(rval, pywbem.Uint32(0))
+
+ # modify file
+ if os.path.isfile(f):
+ os.remove(f)
+ else:
+ os.lchown(f, os.stat(f).st_uid + 1, -1)
+ (rval, oparms) = self.conn.InvokeMethod(
+ MethodName="Invoke",
+ ObjectName=op)
+ self.assertEqual(rval, pywbem.Uint32(2))
+
+ @classmethod
+ def tearDownClass(cls):
+ for pkg_nevra, files in pkg_files:
+ name = re_nevra.match(pkg_nevra).group('name')
+ if is_installed(name) and not verify_pkg(name):
+ remove_pkg(name)
+ if not is_installed(name):
+ install_pkg(nevra=pkg_nevra)
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/src/yum/test/test_yum_installed_package.py b/src/yum/test/test_yum_installed_package.py
new file mode 100755
index 0000000..e78aaaa
--- /dev/null
+++ b/src/yum/test/test_yum_installed_package.py
@@ -0,0 +1,241 @@
+#!/usr/bin/env python
+
+from common import *
+import shutil
+import socket
+import stat
+
+class TestYumInstalledPackage(YumBaseTestCase):
+
+ CLASS_NAME = "LMI_YumInstalledPackage"
+ KEYS = ( "Software", "System")
+
+ def make_op(self, name, epoch, ver, rel, arch, ses=2):
+ op = self.op.copy()
+ pkg_op = pywbem.CIMInstanceName(
+ classname="LMI_YumPackage", namespace="root/cimv2",
+ keybindings={
+ "Name" : name,
+ "SoftwareElementID" : make_nevra(
+ name, epoch, ver, rel, arch, "ALWAYS"),
+ "SoftwareElementState" : pywbem.Uint16(ses),
+ "TargetOperatingSystem" : pywbem.Uint16(36),
+ "Version" : ver })
+ system_op = pywbem.CIMInstanceName(
+ classname="CIM_ComputerSystem", namespace="root/cimv2",
+ keybindings={
+ "CreationClassName" : "CIM_ComputerSystem",
+ "Name" : socket.gethostname() })
+ op["Software"] = pkg_op
+ op["System"] = system_op
+ return op
+
+ def test_get_instance(self):
+ for pkg in packages:
+ if not is_installed(*pkg[:5]):
+ install_pkg(*pkg[:5])
+ op = self.make_op(*pkg[:5])
+ inst = self.conn.GetInstance(InstanceName=op, LocalOnly=False)
+ self.assertIsSubclass(inst.path.classname, self.CLASS_NAME)
+ self.assertIsSubclass(
+ inst.path['System'].classname, op['System'].classname)
+ self.assertIsSubclass(
+ inst.path['Software'].classname, op['Software'].classname)
+ self.assertEqual(len(inst.path.keys()), 2)
+ for key in self.KEYS:
+ self.assertEqual(inst[key], inst.path[key])
+ self.assertEqual(inst['Software'], op['Software'])
+ remove_pkg(pkg.name)
+ op['Software']['SoftwareElementState'] = pywbem.Uint16(1)
+ with self.assertRaises(pywbem.CIMError) as cm:
+ self.conn.GetInstance(InstanceName=op, LocalOnly=False)
+ self.assertEqual(cm.exception.args[0], pywbem.CIM_ERR_NOT_FOUND)
+
+ def test_enum_instances(self):
+ pkg = packages[0]
+ if is_installed(*pkg[:5]):
+ remove_pkg(pkg.name)
+ insts1 = self.conn.EnumerateInstanceNames(ClassName=self.CLASS_NAME)
+ install_pkg(*pkg[:5])
+ insts2 = self.conn.EnumerateInstanceNames(ClassName=self.CLASS_NAME)
+ self.assertEqual(len(insts1) + 1, len(insts2))
+
+ op = self.make_op(*pkg[:5])
+ self.assertIn(op['Software'], (inst['Software'] for inst in insts2))
+ self.assertTrue(all(isinstance(inst, pywbem.CIMInstanceName)
+ for inst in insts1))
+
+ insts1 = self.conn.EnumerateInstances(ClassName=self.CLASS_NAME)
+ remove_pkg(pkg.name)
+ insts2 = self.conn.EnumerateInstances(ClassName=self.CLASS_NAME)
+
+ self.assertEqual(len(insts2) + 1, len(insts1))
+ self.assertIn(op['Software'], (inst['Software'] for inst in insts1))
+ self.assertTrue(all(inst['Software'] == inst.path['Software']
+ for inst in insts1))
+ self.assertTrue(all(inst['System'] == inst.path['System']
+ for inst in insts1))
+
+ def test_create_instance(self):
+ for pkg in packages:
+ if is_installed(pkg.name):
+ remove_pkg(pkg.name)
+ self.assertFalse(is_installed(pkg.name))
+ op = self.make_op(*(list(pkg[:5]) + [1]))
+ inst = pywbem.CIMInstance(classname=op.classname, path=op)
+ inst["Software"] = op["Software"]
+ inst["System"] = op["System"]
+ iname = self.conn.CreateInstance(NewInstance=inst)
+ self.assertIsInstance(iname, pywbem.CIMInstanceName)
+ op["Software"]["SoftwareElementState"] = pywbem.Uint16(2)
+ self.assertEqual(iname["Software"], op["Software"])
+ self.assertIsInstance(iname["System"], pywbem.CIMInstanceName)
+ self.assertIsSubclass(iname["System"].classname,
+ op["System"].classname)
+ self.assertEqual(set(iname.keys()), set(op.keys()))
+ self.assertTrue(is_installed(pkg.name))
+
+ with self.assertRaises(pywbem.CIMError) as cm:
+ self.conn.CreateInstance(NewInstance=inst)
+ self.assertEqual(cm.exception.args[0],
+ pywbem.CIM_ERR_ALREADY_EXISTS)
+
+ def test_delete_instance(self):
+ for pkg in packages:
+ if not is_installed(pkg.name):
+ install_pkg(*pkg[:5])
+ self.assertTrue(is_installed(pkg.name))
+ op = self.make_op(*pkg[:5])
+ self.conn.DeleteInstance(op)
+ self.assertFalse(is_installed(pkg.name))
+ with self.assertRaises(pywbem.CIMError) as cm:
+ self.conn.DeleteInstance(op)
+ self.assertEqual(cm.exception.args[0], pywbem.CIM_ERR_NOT_FOUND)
+
+ def test_check_integrity(self):
+ for pkg_nevra, files in pkg_files:
+ m = re_nevra.match(pkg_nevra)
+ name, epoch, ver, rel, arch = [ m.group(k) for k in (
+ "name", "epoch", "ver", "rel", "arch") ]
+ if ( (is_installed(nevra=pkg_nevra) and not verify_pkg(name))
+ or (is_installed(name) and not is_installed(nevra=pkg_nevra))) :
+ remove_pkg(name)
+ if not is_installed(name):
+ install_pkg(name, epoch, ver, rel, arch)
+ self.assertTrue(is_installed(nevra=pkg_nevra))
+
+ op = self.make_op(name, epoch, ver, rel, arch)
+ (rval, oparms) = self.conn.InvokeMethod(
+ MethodName="CheckIntegrity",
+ ObjectName=op)
+ self.assertEqual(rval, pywbem.Uint32(0)) # check passed
+ self.assertEqual(len(oparms), 1)
+ self.assertIn("Failed", oparms)
+ self.assertEqual(len(oparms["Failed"]), 0)
+
+ cnt_bad = 0
+ for f in files:
+ stats = os.lstat(f)
+ if os.path.islink(f): # modify symbolic link
+ target = os.readlink(f)
+ os.remove(f)
+ os.symlink(target, f) # just touch symlink
+ (rval, oparms) = self.conn.InvokeMethod(
+ MethodName="CheckIntegrity",
+ ObjectName=op)
+ # symlink must pass
+ self.assertEqual(len(oparms["Failed"]), cnt_bad)
+ os.remove(f)
+ # now change target
+ os.symlink("wrong_link_target", f)
+ elif os.path.isdir(f): # check directory
+ os.chmod(f, stats.st_mode) # just touch dir
+ (rval, oparms) = self.conn.InvokeMethod(
+ MethodName="CheckIntegrity",
+ ObjectName=op)
+ # dir must pass
+ self.assertEqual(len(oparms["Failed"]), cnt_bad)
+ # modify read access of directory
+ os.chmod(f, stats.st_mode ^ stat.S_IROTH)
+ else: # modify regular file
+ # just touch file - this is enough to make it fail
+ with open(f, "w+") as fobj: pass
+ cnt_bad += 1
+ (rval, oparms) = self.conn.InvokeMethod(
+ MethodName="CheckIntegrity",
+ ObjectName=op)
+ self.assertEqual(rval, pywbem.Uint32(1))
+ self.assertEqual(len(oparms), 1)
+ self.assertIn("Failed", oparms)
+ self.assertEqual(len(oparms["Failed"]), cnt_bad)
+ self.assertIn(f, (p["Name"] for p in oparms["Failed"]))
+
+ def test_method_update(self):
+ for pkg in packages:
+ if not pkg.updatable: continue
+ if is_installed(pkg.name) and not is_installed(*pkg[:5]):
+ remove_pkg(pkg.name)
+ if not is_installed(pkg.name):
+ install_pkg(*pkg[:5])
+ self.assertTrue(is_installed(*pkg[:5]))
+
+ op = self.make_op(*pkg[:5])
+ op_up = self.make_op(pkg.name, pkg.up_epoch,
+ pkg.up_ver, pkg.up_rel, pkg.arch)
+ (rval, oparms) = self.conn.InvokeMethod(
+ MethodName="Update",
+ ObjectName=op)
+ self.assertEqual(rval, pywbem.Uint16(1))
+ self.assertEqual(len(oparms), 1)
+ self.assertIn("Installed", oparms)
+ self.assertEqual(oparms["Installed"], op_up["Software"])
+ self.assertTrue(is_installed(pkg.name, pkg.up_epoch,
+ pkg.up_ver, pkg.up_rel, pkg.arch))
+
+ (rval, oparms) = self.conn.InvokeMethod(
+ MethodName="Update",
+ ObjectName=op_up)
+ self.assertEqual(rval, pywbem.Uint16(0))
+ self.assertEqual(len(oparms), 1)
+ self.assertEqual(oparms["Installed"], op_up["Software"])
+
+ with self.assertRaises(pywbem.CIMError) as cm:
+ self.conn.InvokeMethod(
+ MethodName="Update",
+ ObjectName=op)
+ self.assertEqual(cm.exception.args[0],
+ pywbem.CIM_ERR_NOT_FOUND)
+
+ remove_pkg(pkg.name)
+ install_pkg(*pkg[:5])
+ self.assertTrue(is_installed(*pkg[:5]))
+
+ (rval, oparms) = self.conn.InvokeMethod(
+ MethodName="Update",
+ ObjectName=op,
+ Epoch=pkg.epoch,
+ Version=pkg.ver,
+ Release=pkg.rel)
+ self.assertEqual(rval, pywbem.Uint16(0))
+ self.assertEqual(oparms["Installed"], op["Software"])
+
+ (rval, oparms) = self.conn.InvokeMethod(
+ MethodName="Update",
+ ObjectName=op,
+ Epoch=pkg.up_epoch,
+ Version=pkg.up_ver,
+ Release=pkg.up_rel)
+ self.assertEqual(rval, pywbem.Uint16(1))
+ self.assertEqual(oparms["Installed"], op_up["Software"])
+
+ @classmethod
+ def tearDownClass(cls):
+ for pkg_nevra, files in pkg_files:
+ name = re_nevra.match(pkg_nevra).group('name')
+ if is_installed(name) and not verify_pkg(name):
+ remove_pkg(name)
+ if not is_installed(name):
+ install_pkg(nevra=pkg_nevra)
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/src/yum/test/test_yum_package.py b/src/yum/test/test_yum_package.py
new file mode 100755
index 0000000..c5b2715
--- /dev/null
+++ b/src/yum/test/test_yum_package.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+
+from common import *
+
+class TestYumPackage(YumBaseTestCase):
+
+ CLASS_NAME = "LMI_YumPackage"
+ KEYS = ( "Name", "SoftwareElementID", "SoftwareElementState"
+ , "TargetOperatingSystem", "Version")
+
+ def make_op(self, name, epoch, ver, rel, arch, ses=2):
+ op = self.op.copy()
+ op["Name"] = name
+ op["SoftwareElementID"] = make_nevra(
+ name, epoch, ver, rel, arch, "ALWAYS")
+ op["SoftwareElementState"] = pywbem.Uint16(ses)
+ op["TargetOperatingSystem"] = pywbem.Uint16(36)
+ op["Version"] = ver
+ return op
+
+ def test_get_instance(self):
+ for pkg in packages:
+ if is_installed(pkg.name):
+ remove_pkg(pkg.name)
+ op = self.make_op(pkg.name, pkg.epoch, pkg.ver,
+ pkg.rel, pkg.arch, 1)
+ inst = self.conn.GetInstance(InstanceName=op, LocalOnly=False)
+ self.assertEqual(inst.path, op)
+ for key in self.KEYS:
+ self.assertTrue(inst.properties.has_key(key))
+ self.assertEqual(inst.path[key], inst[key])
+ self.assertEqual(inst['Release'], pkg.rel)
+ install_pkg(*pkg[:5])
+ op['SoftwareElementState'] = pywbem.Uint16(2)
+ inst = self.conn.GetInstance(InstanceName=op, LocalOnly=False)
+ self.assertEqual(inst.path, op)
+
+ def test_method_install(self):
+ for pkg in packages:
+ if is_installed(pkg.name):
+ remove_pkg(pkg.name)
+ op = self.make_op(pkg.name, pkg.epoch, pkg.ver,
+ pkg.rel, pkg.arch, 1)
+ (rval, oparms) = self.conn.InvokeMethod(
+ MethodName="Install",
+ ObjectName=op)
+ self.assertEqual(rval, pywbem.Uint32(1))
+ self.assertEqual(len(oparms), 1)
+ self.assertTrue(oparms.has_key('Installed'))
+ op['SoftwareElementState'] = pywbem.Uint16(2)
+ self.assertEqual(oparms['Installed'], op)
+ self.assertTrue(is_installed(pkg.name))
+ (rval, oparms) = self.conn.InvokeMethod(
+ MethodName="Install",
+ ObjectName=op)
+ self.assertEqual(rval, pywbem.Uint32(0))
+ self.assertEqual(len(oparms), 1)
+ self.assertEqual(oparms['Installed'], op)
+
+ def test_method_remove(self):
+ for pkg in packages:
+ if not is_installed(pkg.name):
+ install_pkg(*pkg[:5])
+ op = self.make_op(*pkg[:5])
+ (rval, oparms) = self.conn.InvokeMethod(
+ MethodName="Remove",
+ ObjectName=op)
+ self.assertEqual(rval, pywbem.Uint16(1))
+ self.assertEqual(len(oparms), 0)
+ self.assertFalse(is_installed(pkg.name))
+ op["SoftwareElementState"] = pywbem.Uint16(1)
+ (rval, oparms) = self.conn.InvokeMethod(
+ MethodName="Remove",
+ ObjectName=op)
+ self.assertEqual(rval, pywbem.Uint32(0))
+ self.assertEqual(len(oparms), 0)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/src/yum/test/yum_package.sh b/src/yum/test/yum_package.sh
deleted file mode 100755
index 5d81955..0000000
--- a/src/yum/test/yum_package.sh
+++ /dev/null
@@ -1,278 +0,0 @@
-#!/bin/bash
-
-dir=`dirname $0`
-[ -z "$dir" ] && dir=.
-
-CLASS_NAME="LMI_YumPackage"
-. $dir/test_common.sh
-
-declare -A pkg1 pkg2
-if [[ "$fedora_release" = 16 ]]; then
- pkg1=( \
- [name]=python-xlib-doc
- [epoch]=0 \
- [ver]=0.15 \
- [rel]=0.6.rc1.fc16 \
- [arch]=noarch \
- [updatable]=0 \
- )
- pkg2=( \
- [name]=ruby-ri \
- [epoch]=0 \
- [ver]=1.8.7.352 \
- [rel]=1.fc16 \
- [arch]=x86_64 \
- [updatable]=1 \
- [up_epoch]=0 \
- [up_ver]=1.8.7.358 \
- [up_rel]=2.fc16 \
- )
-elif [[ "$fedora_release" = 17 ]]; then
- pkg1=( \
- [name]=python-xlib-doc
- [epoch]=0 \
- [ver]=0.15 \
- [rel]=0.6.rc1.fc17 \
- [arch]=noarch \
- [updatable]=0 \
- )
- pkg2=( \
- [name]=slv2 \
- [epoch]=0 \
- [ver]=0.6.6 \
- [rel]=8.fc17 \
- [arch]=x86_64 \
- [updatable]=1 \
- [up_epoch]=0 \
- [up_ver]=0.6.6 \
- [up_rel]=9.fc17 \
- )
-elif [[ -z "$fedora_release" ]]; then
- echo "failed to get Fedora release number!" 2>&1
- exit 1
-else
- echo "no packages defined for Fedora release $fedora_release" 2>&1
- exit 1
-fi
-keys=(name epoch ver rel arch updatable up_epoch up_ver up_rel)
-
-make_inst_keys() {
- # accepts arguments: name, epoch, ver, rel, arch
- # in this order
- local path='Name="%s",SoftwareElementID="%s",SoftwareElementState="%s",'
- path+='TargetOperatingSystem="%s",Version="%s"'
- printf $path $1 `make_nevra "$@"` 2 36 $3
-}
-
-test_install() {
- local name epoch ver rel arch updatable up_epoch up_ver up_rel;
- read name epoch ver rel arch updatable \
- up_epoch up_ver up_rel <<< "$@"
-
- echo "********************************************************************"
- echo " * TEST INSTALL"
- nevra_arr=($name $epoch $ver $rel $arch)
- nevra=`make_nevra ${nevra_arr[@]}`
- echo -n "$nevra is "
- [ "$updatable" == 0 ] && echo -n "not "
- echo -n "updatable and "
- is_installed $name || echo -n "not "
- echo "installed"
-
- if is_installed $name; then
- echo "removing package \"${nevra}\" with rpm"
- remove $name
- fi
-
- local keys=`make_inst_keys ${nevra_arr[@]}`
- local url="$url/$op.${keys}"
-
- echo "trying to get instance"
- if ! wbemerr gi "$url" |& \
- grep -q '\<SoftwareElementState="\?1"\?'; then
- echo "wrong SoftwareElementState"
- exit 1
- fi
-
- echo "installing $CLASS_NAME: $url"
- if ! wbemerr cm "$url" Install |& \
- grep -q '\<Install:\s*1\s\+Installed'; then
- echo "wrong return code"
- exit 1
- fi
-
- if is_installed $name; then
- echo "successful installation"
- else
- echo "package not installed"
- exit 1
- fi
-
- echo "checking get instance"
- if ! wbemerr gi "$url" |& \
- grep -q '\<SoftwareElementState="\?2"\?'; then
- echo "wrong SoftwareElementState"
- exit 1
- fi
-
- echo "testing installation of already installed package"
- if ! wbemcli cm "${url}" Install |& \
- grep -q '\<Install:\s*0\s\+Installed'; then
- echo "wrong return code"
- exit 1
- fi
-}
-
-test_update() {
- read name epoch ver rel arch updatable \
- up_epoch up_ver up_rel <<< "$@"
-
- echo "********************************************************************"
- echo " * TEST UPDATE"
- if [ "$updatable" == 0 ]; then
- echo "package not updatable"
- exit 1
- fi
-
- nevra_arr=($name $epoch $ver $rel $arch)
- nevra=`make_nevra ${nevra_arr[@]}`
- echo -n "$nevra is "
- [ "$updatable" == 0 ] && echo -n "not "
- echo -n "updatable and "
- is_installed $name || echo -n "not "
- echo "installed"
-
- if is_installed $name; then
- echo "removing package \"${name}\" with rpm"
- remove $name
- fi
-
- local keys=`make_inst_keys ${nevra_arr[@]}`
- local package_url="$url/$op.$keys"
- echo "intalling older package with $CLASS_NAME: $package_url"
- wbemerr cm "$package_url" Install
-
- if is_installed $name; then
- echo "successful installation"
- else
- echo "package not installed"
- exit 1
- fi
-
- echo "updating with LMI_YumInstalledPackage.Update()"
-
- local installed_keys="Software=$op.$keys,System=$computer_system_op"
- local installed_url="$url/`make_op LMI_YumInstalledPackage $installed_keys`"
- if ! wbemerr cm "$installed_url" "Update" | \
- grep -q '\<Update:\s*1\s\+Installed'; then
- echo "wrong return code"
- exit 1
- fi
-
- if is_installed_nevra $name $up_epoch $up_ver $up_rel $arch; then
- echo "successful update"
- else
- echo "update failed"
- exit 1
- fi
-
- keys=`make_inst_keys $name $up_epoch $up_ver $up_rel $arch`
- installed_keys="Software=$op.$keys,System=$computer_system_op"
- local installed_url2="$url/`make_op LMI_YumInstalledPackage $installed_keys`"
- echo "trying to update once more to: $installed_url2"
- if ! wbemerr cm "$installed_url2" "Update" | \
- grep -q '\<Update:\s*0\s\+Installed'; then
- echo "wrong return code"
- exit 1
- fi
-
- echo "removing updated package"
- wbemerr di "$installed_url2"
- if is_installed $name; then
- echo "failed to remove ${name}"
- exit 1
- else
- echo "success"
- fi
-
- echo "installing older package"
- install_pkg "$@" || exit 1
-
- echo "trying to update to not existing version-release"
- wbemerr cm "$installed_url" "Update.Version=\"not-existing-version\"" |&
- grep -q CIM_ERR_NOT_FOUND && echo "ok" || echo "failed"
-
- echo "trying to update to the same version-release"
- wbemerr cm "$installed_url" \
- "Update.Version=\"${ver}\",Release=\"${rel}\"" | \
- grep -q '\<Update:\s*0\s\+Installed' || \
- echo "wrong return code"
-
- if is_installed_nevra $name $epoch $ver $rel $arch; then
- echo "success"
- else
- echo "failed"
- exit 1
- fi
-
- echo "trying to update to the specific version"
- wbemerr cm "$installed_url" \
- "Update.Version=\"${up_ver}\",Release=\"${up_rel}\"" |
- grep -q '\<Update:\s*1\s\+Installed' || \
- echo "wrong return code"
-
- if is_installed_nevra $name $up_epoch $up_ver $up_rel $arch; then
- echo "success"
- else
- echo "failed"
- exit 1
- fi
-}
-
-test_remove() {
- read name epoch ver rel arch updatable \
- up_epoch up_ver up_rel <<< "$@"
-
- echo "********************************************************************"
- echo " * TEST REMOVE"
- nevra_arr=($name $epoch $ver $rel $arch)
- nevra=`make_nevra ${nevra_arr[@]}`
-
- if ! is_installed $name; then
- echo "installing package \"${nevra}\" with yum"
- install_pkg "$@" || exit 1
- fi
-
- local keys=`make_inst_keys ${nevra_arr[@]}`
- local installed_keys="Software=$op.$keys,System=$computer_system_op"
- local installed_url="$url/`make_op LMI_YumInstalledPackage $installed_keys`"
- wbemerr di "$installed_url"
- if is_installed $name; then
- echo "failed to remove ${name}"
- exit 1
- else
- echo "success"
- fi
- local url="$url/$op.$keys"
- if ! wbemerr gi "$url" |& \
- grep -q '\<SoftwareElementState="\?1"\?'; then
- echo "wrong SoftwareElementState"
- exit 1
- fi
-}
-
-
-for p in 1 2
-do
- declare -a args
- for ((i=0; i < ${#keys[@]}; i++)) do
- key=${keys[$i]}
- eval "args[\$i]=\${pkg${p}[\$key]}"
- done
-
- test_install "${args[@]}"
- test_remove "${args[@]}"
- eval "updatable=\${pkg${p}[updatable]}"
- [ "$updatable" == 1 ] && test_update "${args[@]}"
-done
-