[Kimchi-devel] [PATCH 1/3] Adding yumparser module

Daniel Henrique Barboza dhbarboza82 at gmail.com
Thu Jun 4 11:47:17 UTC 2015


From: Daniel Henrique Barboza <dhbarboza82 at gmmail.com>

This module contains:

- functions to write and delete YUM repositories using the .repo files
from the filesystem directly, without the need of an external API.

- a function to return the software update package list by parsing
the output of $yum check-update

Signed-off-by: Daniel Henrique Barboza <dhbarboza82 at gmmail.com>
---
 src/kimchi/yumparser.py | 271 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 271 insertions(+)
 create mode 100644 src/kimchi/yumparser.py

diff --git a/src/kimchi/yumparser.py b/src/kimchi/yumparser.py
new file mode 100644
index 0000000..fcbdc55
--- /dev/null
+++ b/src/kimchi/yumparser.py
@@ -0,0 +1,271 @@
+#
+# Project Kimchi
+#
+# Copyright IBM, Corp. 2015
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+import subprocess
+
+from os import listdir
+from os.path import getmtime, isfile, join, splitext
+
+
+class YumRepoObject(object):
+
+    def _set_base_URL(self, strvalue):
+        self.baseurl = strvalue
+
+    def _set_enabled(self, strvalue):
+        self.enabled = (strvalue == '1')
+
+    def _set_gpgcheck(self, strvalue):
+        self.gpgcheck = (strvalue == '1')
+
+    def _set_gpgkey(self, strvalue):
+        self.gpgkey = strvalue
+
+    def _set_metalink(self, strvalue):
+        self.metalink = strvalue
+
+    def _set_mirrorlist(self, strvalue):
+        self.mirrorlist = strvalue
+
+    def _set_name(self, strvalue):
+        self.name = strvalue
+
+    def __init__(self, repo_id, repofile):
+        self.repo_id = repo_id
+        self.name = None
+        self.baseurl = None
+        self.enabled = True
+        self.gpgcheck = True
+        self.gpgkey = None
+        self.metalink = None
+        self.mirrorlist = None
+        self.repofile = repofile
+        self.attr_setters = {'baseurl': self._set_base_URL,
+                             'enabled': self._set_enabled,
+                             'gpgcheck': self._set_gpgcheck,
+                             'gpgkey': self._set_gpgkey,
+                             'name': self._set_name,
+                             'metalink': self._set_metalink,
+                             'mirrorlist': self._set_mirrorlist}
+
+    def set_attribute(self, key, value):
+        attr_setter = self.attr_setters.get(key)
+        if attr_setter:
+            return attr_setter(value)
+
+    def get_attribute_str(self, key):
+        if key not in self.attr_setters.keys():
+            return None
+        if key == 'enabled' or key == 'gpgcheck':
+            str_value = '1' if getattr(self, key) is True else '0'
+        else:
+            str_value = getattr(self, key)
+
+        if str_value is None:
+            return None
+
+        return key + '=' + str_value
+
+    def get_attributes(self):
+        return self.attr_setters.keys()
+
+    def enable(self):
+        self.enabled = True
+
+    def disable(self):
+        self.enabled = False
+
+    def __str__(self):
+        str_obj = '[' + self.repo_id + ']' + '\n'
+        for key in self.get_attributes():
+            if self.get_attribute_str(key) is not None:
+                str_obj += self.get_attribute_str(key) + '\n'
+        return str_obj
+
+
+def get_repo_files():
+    def _is_repository_file(f):
+        _, f_extension = splitext(f)
+        return isfile(f) and (f_extension == '.repo')
+
+    YUM_REPO_DIR = '/etc/yum.repos.d'
+    return [YUM_REPO_DIR+'/'+f for f in listdir(YUM_REPO_DIR)
+            if _is_repository_file(YUM_REPO_DIR+'/'+f)]
+
+
+def _ignore_line_repo_file(line):
+    return line.startswith("#") or '=' not in line
+
+
+def _get_repos_from_file(repo_file):
+    repos_from_file = {}
+    current_repo = None
+    current_repo_id = None
+    with open(repo_file) as f:
+        for line in f.readlines():
+            line = line.strip()
+            if line.startswith("["):
+                if current_repo is not None:
+                    repos_from_file[current_repo_id] = current_repo
+                current_repo_id = line.strip('[]')
+                current_repo = YumRepoObject(current_repo_id, repo_file)
+                continue
+            if _ignore_line_repo_file(line):
+                continue
+            key, value = line.split('=', 1)
+            key = key.strip()
+            value = value.strip()
+            current_repo.set_attribute(key, value)
+
+        # add the last repo from file
+        repos_from_file[current_repo_id] = current_repo
+
+    return repos_from_file
+
+
+def get_yum_repositories():
+    repo_files = get_repo_files()
+    repos = {}
+    for yum_repo in repo_files:
+        repos.update(_get_repos_from_file(yum_repo))
+
+    return repos
+
+
+def _retrieve_repo_line_index(data, repo):
+    repo_entry = '[' + repo.repo_id + ']\n'
+    try:
+        repo_index = data.index(repo_entry)
+    except:
+        return None
+    return repo_index
+
+
+def _update_repo_file_data(data, repo, repo_index):
+    remaining_repo_attrs = repo.get_attributes()
+
+    for i in range(repo_index + 1, len(data)):
+        line = data[i].strip()
+        if line.startswith('['):
+            break
+        if _ignore_line_repo_file(line):
+            continue
+        key, _ = line.split('=', 1)
+        key = key.strip()
+        attr_str = repo.get_attribute_str(key)
+        if attr_str is None:
+            continue
+        remaining_repo_attrs.remove(key)
+        data[i] = attr_str + '\n'
+
+    for attr in remaining_repo_attrs:
+        attr_str = repo.get_attribute_str(attr)
+        if attr_str is None:
+            continue
+        data.insert(repo_index+1, attr_str + '\n')
+
+    return data
+
+
+def write_repo_to_file(repo):
+    with open(repo.repofile) as f:
+        data = f.readlines()
+
+    repo_index = _retrieve_repo_line_index(data, repo)
+    if repo_index is None:
+        return
+
+    data = _update_repo_file_data(data, repo, repo_index)
+
+    with open(repo.repofile, 'w') as f:
+        f.writelines(data)
+
+
+def _get_last_line_repo(data, repo_index):
+    stop_delete_index = None
+    for i in range(repo_index+1, len(data)):
+        line = data[i].strip()
+        if line.startswith('['):
+            stop_delete_index = i - 1
+            break
+    if stop_delete_index is None:
+        stop_delete_index = len(data) - 1
+
+    return stop_delete_index
+
+
+def _remove_repo_file_data(data, repo_index):
+    last_line_repo = _get_last_line_repo(data, repo_index)
+    for i in range(last_line_repo, repo_index - 1, -1):
+        data.pop(i)
+    return data
+
+
+def delete_repo_from_file(repo):
+    with open(repo.repofile) as f:
+        data = f.readlines()
+
+    repo_index = _retrieve_repo_line_index(data, repo)
+    if repo_index is None:
+        return
+
+    data = _remove_repo_file_data(data, repo_index)
+
+    with open(repo.repofile, 'w') as f:
+        f.writelines(data)
+
+
+class YumUpdatePackageObject(object):
+
+    def __init__(self, name, arch, version, repo):
+        self.name = name
+        self.arch = arch
+        self.version = version
+        self.ui_from_repo = repo
+
+
+def _get_yum_checkupdate_output():
+    cmd = ['yum', 'check-update', '-d0']
+    yum_update_cmd = subprocess.Popen(cmd,
+                                      stdout=subprocess.PIPE,
+                                      stderr=subprocess.PIPE)
+    out, error = yum_update_cmd.communicate()
+    if error != '':
+        return None
+
+    return out.split()
+
+
+def get_yum_packages_list_update():
+    yum_checkupdate_output = _get_yum_checkupdate_output()
+    if yum_checkupdate_output is None:
+        return None
+
+    packages = []
+    index = 0
+    while index < len(yum_checkupdate_output):
+        name_arch = yum_checkupdate_output[index]
+        index += 1
+        version = yum_checkupdate_output[index]
+        index += 1
+        repo = yum_checkupdate_output[index]
+        index += 1
+        name, arch = name_arch.rsplit('.', 1)
+        packages.append(YumUpdatePackageObject(name, arch, version, repo))
+
+    return packages
-- 
2.1.0




More information about the Kimchi-devel mailing list