[master 6/17] Add tasks infrastructure to tasks directory.
mulkieran
installerbot-noreply at redhat.com
Thu Apr 23 16:39:43 UTC 2015
From: mulhern <amulhern at redhat.com>
Related: #12
Signed-off-by: mulhern <amulhern at redhat.com>
---
blivet/tasks/__init__.py | 0
blivet/tasks/availability.py | 192 +++++++++++++++++++++++++++++++++++++++++++
blivet/tasks/task.py | 86 +++++++++++++++++++
python-blivet.spec | 1 +
setup.py | 2 +-
5 files changed, 280 insertions(+), 1 deletion(-)
create mode 100644 blivet/tasks/__init__.py
create mode 100644 blivet/tasks/availability.py
create mode 100644 blivet/tasks/task.py
diff --git a/blivet/tasks/__init__.py b/blivet/tasks/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py
new file mode 100644
index 0000000..b868e39
--- /dev/null
+++ b/blivet/tasks/availability.py
@@ -0,0 +1,192 @@
+# availability.py
+# Class for tracking availability of an application.
+#
+# Copyright (C) 2014-2015 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# the GNU General Public License v.2, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY expressed or implied, including the implied warranties of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details. You should have received a copy of the
+# GNU General Public License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
+# source code or documentation are not subject to the GNU General Public
+# License and may only be used or replicated with the express permission of
+# Red Hat, Inc.
+#
+# Red Hat Author(s): Anne Mulhern <amulhern at redhat.com>
+
+import abc
+from distutils.version import LooseVersion
+
+from six import add_metaclass
+
+from gi.repository import BlockDev as blockdev
+
+from .. import util
+from ..errors import AvailabilityError
+
+class ExternalResource(object):
+ """ An application. """
+
+ def __init__(self, method, name):
+ """ Initializes an instance of an application.
+
+ :param method: A method object
+ :type method: :class:`Method`
+ :param str name: the name of the application
+ """
+ self._method = method
+ self.name = name
+
+ def __str__(self):
+ return self.name
+
+ # Results of these methods may change at runtime, depending on system
+ # state.
+
+ @property
+ def available(self):
+ """ Whether the resource is available.
+
+ :returns: True if the resource is available, otherwise False
+ :rtype: bool
+ """
+ return self._method.available(self)
+
+ at add_metaclass(abc.ABCMeta)
+class Method(object):
+ """ A collection of methods for a particular application task. """
+
+ @abc.abstractmethod
+ def available(self, resource):
+ """ Returns True if the resource is available.
+
+ :param resource: any external resource
+ :type resource: :class:`ExternalResource`
+
+ :returns: True if the application is available
+ :rtype: bool
+ """
+ raise NotImplementedError()
+
+class Path(Method):
+ """ Methods for when application is found in PATH. """
+
+ def available(self, resource):
+ """ Returns True if the name of the application is in the path.
+
+ :param resource: any application
+ :type resource: :class:`ExternalResource`
+
+ :returns: True if the name of the application is in the path
+ :rtype: bool
+ """
+ return bool(util.find_program_in_path(resource.name))
+
+Path = Path()
+
+class PackageInfo(object):
+
+ def __init__(self, package_name, required_version=None):
+ """ Initializer.
+
+ :param str package_name: the name of the package
+ :param required_version: the required version for this package
+ :type required_version: :class:`distutils.LooseVersion` or NoneType
+ """
+ self.package_name = package_name
+ self.required_version = required_version
+
+ def __str__(self):
+ return "%s-%s" % (self.package_name, self.required_version)
+
+class PackageMethod(Method):
+ """ Methods for checking the package version of the external resource. """
+
+ def __init__(self, package=None):
+ """ Initializer.
+
+ :param :class:`PackageInfo` package:
+ """
+ self.package = package
+
+ @property
+ def packageVersion(self):
+ args = ["rpm", "-q", "--queryformat", "%{VERSION}", self.package.package_name]
+ try:
+ (rc, out) = util.run_program_and_capture_output(args)
+ if rc != 0:
+ raise AvailabilityError("Could not determine package version for %s" % self.package.package_name)
+ except OSError as e:
+ raise AvailabilityError("Could not determine package version for %s: %s" % (self.package.package_name, e))
+
+ return LooseVersion(out)
+
+ def available(self, resource):
+ return Path.available(resource) and \
+ self.package.required_version is None or self.packageVersion >= self.package.required_version
+
+class BlockDevMethod(Method):
+ """ Methods for when application is actually a libblockdev plugin. """
+
+ def available(self, resource):
+ """ Returns True if the plugin is loaded.
+
+ :param resource: a libblockdev plugin
+ :type resource: :class:`ExternalResource`
+
+ :returns: True if the name of the plugin is loaded
+ :rtype: bool
+ """
+ return resource.name in blockdev.get_available_plugin_names()
+
+BlockDevMethod = BlockDevMethod()
+
+def application(name):
+ """ Construct an external resource that is an application.
+
+ This application will be available if its name can be found in $PATH.
+ """
+ return ExternalResource(Path, name)
+
+def application_by_package(name, package_method):
+ """ Construct an external resource that is an application.
+
+ This application will be available if its name can be found in $PATH
+ AND its package version is at least the required version.
+
+ :param :class:`PackageMethod` package_method: the package method
+ """
+ return ExternalResource(package_method, name)
+
+def blockdev_plugin(name):
+ """ Construct an external resource that is a libblockdev plugin. """
+ return ExternalResource(BlockDevMethod, name)
+
+# blockdev plugins
+BLOCKDEV_BTRFS_PLUGIN = blockdev_plugin("btrfs")
+BLOCKDEV_CRYPTO_PLUGIN = blockdev_plugin("crypto")
+BLOCKDEV_DM_PLUGIN = blockdev_plugin("dm")
+BLOCKDEV_LOOP_PLUGIN = blockdev_plugin("loop")
+BLOCKDEV_LVM_PLUGIN = blockdev_plugin("lvm")
+BLOCKDEV_MDRAID_PLUGIN = blockdev_plugin("mdraid")
+BLOCKDEV_MPATH_PLUGIN = blockdev_plugin("mpath")
+BLOCKDEV_SWAP_PLUGIN = blockdev_plugin("swap")
+
+# packages
+E2FSPROGS_PACKAGE = PackageMethod(PackageInfo("e2fsprogs", LooseVersion("1.41.0")))
+
+# applications
+DOSFSLABEL_APP = application("dosfslabel")
+E2LABEL_APP = application_by_package("e2label", E2FSPROGS_PACKAGE)
+JFSTUNE_APP = application("jfs_tune")
+NTFSLABEL_APP = application("ntfslabel")
+NTFSRESIZE_APP = application("ntfsresize")
+RESIZE2FS_APP = application_by_package("resize2fs", E2FSPROGS_PACKAGE)
+XFSADMIN_APP = application("xfs_admin")
+
+MOUNT_APP = application("mount")
diff --git a/blivet/tasks/task.py b/blivet/tasks/task.py
new file mode 100644
index 0000000..9a519ff
--- /dev/null
+++ b/blivet/tasks/task.py
@@ -0,0 +1,86 @@
+# task.py
+# Abstract class for tasks.
+#
+# Copyright (C) 2015 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# the GNU General Public License v.2, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY expressed or implied, including the implied warranties of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details. You should have received a copy of the
+# GNU General Public License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
+# source code or documentation are not subject to the GNU General Public
+# License and may only be used or replicated with the express permission of
+# Red Hat, Inc.
+#
+# Red Hat Author(s): Anne Mulhern <amulhern at redhat.com>
+
+import abc
+
+from six import add_metaclass
+
+ at add_metaclass(abc.ABCMeta)
+class Task(object):
+ """ An abstract class that represents some task. """
+
+ # Whether or not the functionality is implemented in the task class.
+ # It is True by default. Only NotImplementedClass and its descendants
+ # should have a False value.
+ implemented = True
+
+ description = abc.abstractproperty(doc="Brief description for this task.")
+
+ @property
+ def availabilityErrors(self):
+ """ Reasons if this task or the tasks it depends on are unavailable. """
+ return self._availabilityErrors + \
+ [e for t in self.dependsOn for e in t.availabilityErrors]
+
+ _availabilityErrors = abc.abstractproperty(
+ doc="Reasons if the necessary external tools are unavailable.")
+
+ dependsOn = abc.abstractproperty(doc="tasks that this task depends on")
+
+ @abc.abstractmethod
+ def doTask(self, *args, **kwargs):
+ """ Do the task for this class. """
+ raise NotImplementedError()
+
+class UnimplementedTask(Task):
+ """ A null Task, which returns a negative or empty for all properties."""
+
+ description = "an unimplemented task"
+ implemented = False
+
+ @property
+ def _availabilityErrors(self):
+ return ["Not implemented task can not succeed."]
+
+ dependsOn = []
+
+ def doTask(self, *args, **kwargs):
+ raise NotImplementedError()
+
+ at add_metaclass(abc.ABCMeta)
+class BasicApplication(Task):
+ """ A task representing an application. """
+
+ ext = abc.abstractproperty(doc="The object representing the external resource.")
+
+ # TASK methods
+
+ @property
+ def _availabilityErrors(self):
+ errors = []
+ if not self.ext.available:
+ errors.append("application %s is not available" % self.ext)
+
+ return errors
+
+ @property
+ def dependsOn(self):
+ return []
diff --git a/python-blivet.spec b/python-blivet.spec
index c01f462..73d981b 100644
--- a/python-blivet.spec
+++ b/python-blivet.spec
@@ -41,6 +41,7 @@ Requires: libselinux-python
Requires: libblockdev >= %{libblockdevver}
Requires: libblockdev-plugins-all >= %{libblockdevver}
Requires: libselinux-python
+Requires: rpm
%description
The python-blivet package is a python module for examining and modifying
diff --git a/setup.py b/setup.py
index 83a23ff..e7ac91c 100644
--- a/setup.py
+++ b/setup.py
@@ -36,4 +36,4 @@ def add_member_order_option(files):
author='David Lehman', author_email='dlehman at redhat.com',
url='http://fedoraproject.org/wiki/blivet',
data_files=data_files,
- packages=['blivet', 'blivet.devices', 'blivet.devicelibs', 'blivet.formats'])
+ packages=['blivet', 'blivet.devices', 'blivet.devicelibs', 'blivet.formats', 'blivet.tasks'])
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/1b066f60e887cac16dde8a8530bd2a6e49c40081
More information about the anaconda-patches
mailing list