yum: take care of stale/invalid yum.pid (#58457)
* yum: take care of stale/invalid yum.pid * Add changelog
This commit is contained in:
parent
939e2b4c79
commit
5064e67d37
6 changed files with 96 additions and 7 deletions
2
changelogs/fragments/yum-handle-stale-lock-file.yaml
Normal file
2
changelogs/fragments/yum-handle-stale-lock-file.yaml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
bugfixes:
|
||||||
|
- yum - handle stale/invalid yum.pid lock file (https://github.com/ansible/ansible/issues/57189)
|
|
@ -126,15 +126,25 @@ class YumDnf(with_metaclass(ABCMeta, object)):
|
||||||
# default isn't a bad idea
|
# default isn't a bad idea
|
||||||
self.lockfile = '/var/run/yum.pid'
|
self.lockfile = '/var/run/yum.pid'
|
||||||
|
|
||||||
|
def is_lockfile_pid_valid(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def _is_lockfile_present(self):
|
||||||
|
return (os.path.isfile(self.lockfile) or glob.glob(self.lockfile)) and self.is_lockfile_pid_valid()
|
||||||
|
|
||||||
def wait_for_lock(self):
|
def wait_for_lock(self):
|
||||||
'''Poll until the lock is removed if timeout is a positive number'''
|
'''Poll until the lock is removed if timeout is a positive number'''
|
||||||
if (os.path.isfile(self.lockfile) or glob.glob(self.lockfile)):
|
|
||||||
if self.lock_timeout > 0:
|
if not self._is_lockfile_present():
|
||||||
for iteration in range(0, self.lock_timeout):
|
return
|
||||||
time.sleep(1)
|
|
||||||
if not os.path.isfile(self.lockfile) and not glob.glob(self.lockfile):
|
if self.lock_timeout > 0:
|
||||||
return
|
for iteration in range(0, self.lock_timeout):
|
||||||
self.module.fail_json(msg='{0} lockfile is held by another process'.format(self.pkg_mgr_name))
|
time.sleep(1)
|
||||||
|
if not self._is_lockfile_present():
|
||||||
|
return
|
||||||
|
|
||||||
|
self.module.fail_json(msg='{0} lockfile is held by another process'.format(self.pkg_mgr_name))
|
||||||
|
|
||||||
def listify_comma_sep_strings_in_list(self, some_list):
|
def listify_comma_sep_strings_in_list(self, some_list):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -329,6 +329,11 @@ class DnfModule(YumDnf):
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.with_modules = False
|
self.with_modules = False
|
||||||
|
|
||||||
|
def is_lockfile_pid_valid(self):
|
||||||
|
# FIXME? it looks like DNF takes care of invalid lock files itself?
|
||||||
|
# https://github.com/ansible/ansible/issues/57189
|
||||||
|
return True
|
||||||
|
|
||||||
def _sanitize_dnf_error_msg(self, spec, error):
|
def _sanitize_dnf_error_msg(self, spec, error):
|
||||||
"""
|
"""
|
||||||
For unhandled dnf.exceptions.Error scenarios, there are certain error
|
For unhandled dnf.exceptions.Error scenarios, there are certain error
|
||||||
|
|
|
@ -336,6 +336,7 @@ from ansible.module_utils._text import to_native, to_text
|
||||||
from ansible.module_utils.urls import fetch_url
|
from ansible.module_utils.urls import fetch_url
|
||||||
from ansible.module_utils.yumdnf import YumDnf, yumdnf_argument_spec
|
from ansible.module_utils.yumdnf import YumDnf, yumdnf_argument_spec
|
||||||
|
|
||||||
|
import errno
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import tempfile
|
import tempfile
|
||||||
|
@ -410,6 +411,44 @@ class YumModule(YumDnf):
|
||||||
else:
|
else:
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
|
def is_lockfile_pid_valid(self):
|
||||||
|
try:
|
||||||
|
with open(self.lockfile, 'r') as f:
|
||||||
|
oldpid = int(f.readline())
|
||||||
|
except ValueError:
|
||||||
|
# invalid data
|
||||||
|
os.unlink(self.lockfile)
|
||||||
|
return False
|
||||||
|
except (IOError, OSError) as e:
|
||||||
|
self.module.fail_json(msg="Failure opening %s: %s" % (self.lockfile, to_native(e)))
|
||||||
|
|
||||||
|
if oldpid == os.getpid():
|
||||||
|
# that's us?
|
||||||
|
os.unlink(self.lockfile)
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open("/proc/%d/stat" % oldpid, 'r') as f:
|
||||||
|
stat = f.readline()
|
||||||
|
|
||||||
|
if stat.split()[2] == 'Z':
|
||||||
|
# Zombie
|
||||||
|
os.unlink(self.lockfile)
|
||||||
|
return False
|
||||||
|
except IOError:
|
||||||
|
try:
|
||||||
|
os.kill(oldpid, 0)
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno == errno.ESRCH:
|
||||||
|
# No such process
|
||||||
|
os.unlink(self.lockfile)
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.module.fail_json(msg="Unable to check PID %s in %s: %s" % (oldpid, self.lockfile, to_native(e)))
|
||||||
|
|
||||||
|
# another copy seems to be running
|
||||||
|
return True
|
||||||
|
|
||||||
def yum_base(self):
|
def yum_base(self):
|
||||||
my = yum.YumBase()
|
my = yum.YumBase()
|
||||||
my.preconf.debuglevel = 0
|
my.preconf.debuglevel = 0
|
||||||
|
|
28
test/integration/targets/yum/tasks/lock.yml
Normal file
28
test/integration/targets/yum/tasks/lock.yml
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
- block:
|
||||||
|
- name: Make sure testing package is not installed
|
||||||
|
yum:
|
||||||
|
name: sos
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Create bogus lock file
|
||||||
|
copy:
|
||||||
|
content: bogus content for this lock file
|
||||||
|
dest: /var/run/yum.pid
|
||||||
|
|
||||||
|
- name: Install a package, lock file should be deleted by the module
|
||||||
|
yum:
|
||||||
|
name: sos
|
||||||
|
state: present
|
||||||
|
register: yum_result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- yum_result is success
|
||||||
|
|
||||||
|
always:
|
||||||
|
- name: Clean up
|
||||||
|
yum:
|
||||||
|
name: sos
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
when: ansible_pkg_mgr == 'yum'
|
|
@ -60,3 +60,8 @@
|
||||||
- import_tasks: check_mode_consistency.yml
|
- import_tasks: check_mode_consistency.yml
|
||||||
when:
|
when:
|
||||||
- (ansible_distribution in ['RedHat', 'CentOS', 'ScientificLinux'] and ansible_distribution_major_version|int == 7)
|
- (ansible_distribution in ['RedHat', 'CentOS', 'ScientificLinux'] and ansible_distribution_major_version|int == 7)
|
||||||
|
|
||||||
|
|
||||||
|
- import_tasks: lock.yml
|
||||||
|
when:
|
||||||
|
- ansible_distribution in ['RedHat', 'CentOS', 'ScientificLinux']
|
||||||
|
|
Loading…
Reference in a new issue