Revision 9d1b963f lib/utils/__init__.py
b/lib/utils/__init__.py | ||
---|---|---|
60 | 60 |
from ganeti.utils.log import * # pylint: disable-msg=W0401 |
61 | 61 |
from ganeti.utils.hash import * # pylint: disable-msg=W0401 |
62 | 62 |
from ganeti.utils.wrapper import * # pylint: disable-msg=W0401 |
63 |
from ganeti.utils.filelock import * # pylint: disable-msg=W0401 |
|
63 | 64 |
|
64 | 65 |
|
65 | 66 |
#: when set to True, L{RunCmd} is disabled |
... | ... | |
2549 | 2550 |
return bool(exitcode) |
2550 | 2551 |
|
2551 | 2552 |
|
2552 |
def LockFile(fd): |
|
2553 |
"""Locks a file using POSIX locks. |
|
2554 |
|
|
2555 |
@type fd: int |
|
2556 |
@param fd: the file descriptor we need to lock |
|
2557 |
|
|
2558 |
""" |
|
2559 |
try: |
|
2560 |
fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) |
|
2561 |
except IOError, err: |
|
2562 |
if err.errno == errno.EAGAIN: |
|
2563 |
raise errors.LockError("File already locked") |
|
2564 |
raise |
|
2565 |
|
|
2566 |
|
|
2567 | 2553 |
def ReadWatcherPauseFile(filename, now=None, remove_after=3600): |
2568 | 2554 |
"""Reads the watcher pause file. |
2569 | 2555 |
|
... | ... | |
2658 | 2644 |
WriteFile(filename, mode=0400, data=key_pem + cert_pem) |
2659 | 2645 |
|
2660 | 2646 |
|
2661 |
class FileLock(object): |
|
2662 |
"""Utility class for file locks. |
|
2663 |
|
|
2664 |
""" |
|
2665 |
def __init__(self, fd, filename): |
|
2666 |
"""Constructor for FileLock. |
|
2667 |
|
|
2668 |
@type fd: file |
|
2669 |
@param fd: File object |
|
2670 |
@type filename: str |
|
2671 |
@param filename: Path of the file opened at I{fd} |
|
2672 |
|
|
2673 |
""" |
|
2674 |
self.fd = fd |
|
2675 |
self.filename = filename |
|
2676 |
|
|
2677 |
@classmethod |
|
2678 |
def Open(cls, filename): |
|
2679 |
"""Creates and opens a file to be used as a file-based lock. |
|
2680 |
|
|
2681 |
@type filename: string |
|
2682 |
@param filename: path to the file to be locked |
|
2683 |
|
|
2684 |
""" |
|
2685 |
# Using "os.open" is necessary to allow both opening existing file |
|
2686 |
# read/write and creating if not existing. Vanilla "open" will truncate an |
|
2687 |
# existing file -or- allow creating if not existing. |
|
2688 |
return cls(os.fdopen(os.open(filename, os.O_RDWR | os.O_CREAT), "w+"), |
|
2689 |
filename) |
|
2690 |
|
|
2691 |
def __del__(self): |
|
2692 |
self.Close() |
|
2693 |
|
|
2694 |
def Close(self): |
|
2695 |
"""Close the file and release the lock. |
|
2696 |
|
|
2697 |
""" |
|
2698 |
if hasattr(self, "fd") and self.fd: |
|
2699 |
self.fd.close() |
|
2700 |
self.fd = None |
|
2701 |
|
|
2702 |
def _flock(self, flag, blocking, timeout, errmsg): |
|
2703 |
"""Wrapper for fcntl.flock. |
|
2704 |
|
|
2705 |
@type flag: int |
|
2706 |
@param flag: operation flag |
|
2707 |
@type blocking: bool |
|
2708 |
@param blocking: whether the operation should be done in blocking mode. |
|
2709 |
@type timeout: None or float |
|
2710 |
@param timeout: for how long the operation should be retried (implies |
|
2711 |
non-blocking mode). |
|
2712 |
@type errmsg: string |
|
2713 |
@param errmsg: error message in case operation fails. |
|
2714 |
|
|
2715 |
""" |
|
2716 |
assert self.fd, "Lock was closed" |
|
2717 |
assert timeout is None or timeout >= 0, \ |
|
2718 |
"If specified, timeout must be positive" |
|
2719 |
assert not (flag & fcntl.LOCK_NB), "LOCK_NB must not be set" |
|
2720 |
|
|
2721 |
# When a timeout is used, LOCK_NB must always be set |
|
2722 |
if not (timeout is None and blocking): |
|
2723 |
flag |= fcntl.LOCK_NB |
|
2724 |
|
|
2725 |
if timeout is None: |
|
2726 |
self._Lock(self.fd, flag, timeout) |
|
2727 |
else: |
|
2728 |
try: |
|
2729 |
Retry(self._Lock, (0.1, 1.2, 1.0), timeout, |
|
2730 |
args=(self.fd, flag, timeout)) |
|
2731 |
except RetryTimeout: |
|
2732 |
raise errors.LockError(errmsg) |
|
2733 |
|
|
2734 |
@staticmethod |
|
2735 |
def _Lock(fd, flag, timeout): |
|
2736 |
try: |
|
2737 |
fcntl.flock(fd, flag) |
|
2738 |
except IOError, err: |
|
2739 |
if timeout is not None and err.errno == errno.EAGAIN: |
|
2740 |
raise RetryAgain() |
|
2741 |
|
|
2742 |
logging.exception("fcntl.flock failed") |
|
2743 |
raise |
|
2744 |
|
|
2745 |
def Exclusive(self, blocking=False, timeout=None): |
|
2746 |
"""Locks the file in exclusive mode. |
|
2747 |
|
|
2748 |
@type blocking: boolean |
|
2749 |
@param blocking: whether to block and wait until we |
|
2750 |
can lock the file or return immediately |
|
2751 |
@type timeout: int or None |
|
2752 |
@param timeout: if not None, the duration to wait for the lock |
|
2753 |
(in blocking mode) |
|
2754 |
|
|
2755 |
""" |
|
2756 |
self._flock(fcntl.LOCK_EX, blocking, timeout, |
|
2757 |
"Failed to lock %s in exclusive mode" % self.filename) |
|
2758 |
|
|
2759 |
def Shared(self, blocking=False, timeout=None): |
|
2760 |
"""Locks the file in shared mode. |
|
2761 |
|
|
2762 |
@type blocking: boolean |
|
2763 |
@param blocking: whether to block and wait until we |
|
2764 |
can lock the file or return immediately |
|
2765 |
@type timeout: int or None |
|
2766 |
@param timeout: if not None, the duration to wait for the lock |
|
2767 |
(in blocking mode) |
|
2768 |
|
|
2769 |
""" |
|
2770 |
self._flock(fcntl.LOCK_SH, blocking, timeout, |
|
2771 |
"Failed to lock %s in shared mode" % self.filename) |
|
2772 |
|
|
2773 |
def Unlock(self, blocking=True, timeout=None): |
|
2774 |
"""Unlocks the file. |
|
2775 |
|
|
2776 |
According to C{flock(2)}, unlocking can also be a nonblocking |
|
2777 |
operation:: |
|
2778 |
|
|
2779 |
To make a non-blocking request, include LOCK_NB with any of the above |
|
2780 |
operations. |
|
2781 |
|
|
2782 |
@type blocking: boolean |
|
2783 |
@param blocking: whether to block and wait until we |
|
2784 |
can lock the file or return immediately |
|
2785 |
@type timeout: int or None |
|
2786 |
@param timeout: if not None, the duration to wait for the lock |
|
2787 |
(in blocking mode) |
|
2788 |
|
|
2789 |
""" |
|
2790 |
self._flock(fcntl.LOCK_UN, blocking, timeout, |
|
2791 |
"Failed to unlock %s" % self.filename) |
|
2792 |
|
|
2793 |
|
|
2794 | 2647 |
def SignalHandled(signums): |
2795 | 2648 |
"""Signal Handled decoration. |
2796 | 2649 |
|
Also available in: Unified diff