ffd2e4c4b2adeead4628688ff12d20008e4a97da
[invirt/packages/invirt-base.git] / python / invirt / common.py
1 import unittest
2 from fcntl import flock, LOCK_EX, LOCK_SH, LOCK_UN
3 import contextlib as clib
4 import subprocess
5
6 class InvirtConfigError(AttributeError):
7     pass
8
9
10 @clib.contextmanager
11 def lock_file(path, exclusive = True):
12     with clib.closing(open(path, 'w')) as f:
13         if exclusive:
14             locktype = LOCK_EX
15         else:
16             locktype = LOCK_SH
17         flock(f, locktype)
18         try:
19             yield
20         finally:
21             flock(f, LOCK_UN)
22
23 def captureOutput(popen_args, stdin_str=None, *args, **kwargs):
24     """Capture stdout from a command.
25
26     This method will proxy the arguments to subprocess.Popen. It
27     returns the output from the command if the call succeeded and
28     raises an exception if the process returns a non-0 value.
29
30     This is intended to be a variant on the subprocess.check_call
31     function that also allows you access to the output from the
32     command.
33     """
34     if 'stdin' not in kwargs:
35         kwargs['stdin'] = subprocess.PIPE
36     if 'stdout' not in kwargs:
37         kwargs['stdout'] = subprocess.PIPE
38     if 'stderr' not in kwargs:
39         kwargs['stderr'] = subprocess.PIPE
40     p = subprocess.Popen(popen_args, *args, **kwargs)
41     out, err = p.communicate(stdin_str)
42     if p.returncode:
43         raise subprocess.CalledProcessError(p.returncode, '%s, stdout: %s, stderr: %s' %
44                                             (popen_args, out, err))
45     return out
46
47 #
48 # Exceptions.
49 #
50
51 class InvalidInput(Exception):
52     """Exception for user-provided input is invalid but maybe in good faith.
53
54     This would include setting memory to negative (which might be a
55     typo) but not setting an invalid boot CD (which requires bypassing
56     the select box).
57     """
58     def __init__(self, err_field, err_value, expl=None):
59         Exception.__init__(self, expl)
60         self.err_field = err_field
61         self.err_value = err_value
62
63 class CodeError(Exception):
64     """Exception for internal errors or bad faith input."""
65     pass
66
67 #
68 # Tests.
69 #
70
71