author | Tero Marttila <terom@paivola.fi> |
Mon, 22 Apr 2013 00:36:14 +0300 | |
changeset 72 | 2d2494132e9c |
parent 68 | adc190def3b1 |
permissions | -rw-r--r-- |
5
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
1 |
""" |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
2 |
Invoke external commands. |
72 | 3 |
|
4 |
XXX: replace with pvl.invoke |
|
5
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
5 |
""" |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
6 |
|
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
7 |
import subprocess |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
8 |
import logging |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
9 |
|
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
10 |
log = logging.getLogger('pvl.backup.invoke') |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
11 |
|
68
adc190def3b1
pvl.backup.invoke: implement sudo=True to exec via sudo
Tero Marttila <terom@paivola.fi>
parents:
27
diff
changeset
|
12 |
SUDO = '/usr/bin/sudo' |
adc190def3b1
pvl.backup.invoke: implement sudo=True to exec via sudo
Tero Marttila <terom@paivola.fi>
parents:
27
diff
changeset
|
13 |
|
5
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
14 |
class InvokeError (Exception) : |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
15 |
def __init__ (self, cmd, exit) : |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
16 |
self.cmd = cmd |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
17 |
self.exit = exit |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
18 |
|
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
19 |
def __str__ (self) : |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
20 |
return "{cmd} failed: {exit}".format(cmd=self.cmd, exit=self.exit) |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
21 |
|
68
adc190def3b1
pvl.backup.invoke: implement sudo=True to exec via sudo
Tero Marttila <terom@paivola.fi>
parents:
27
diff
changeset
|
22 |
def invoke (cmd, args, data=None, sudo=False) : |
5
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
23 |
""" |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
24 |
Invoke a command directly. |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
25 |
|
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
26 |
data: data to pass in on stdin, returning stdout. |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
27 |
if given as False, passes through our process stdin/out |
68
adc190def3b1
pvl.backup.invoke: implement sudo=True to exec via sudo
Tero Marttila <terom@paivola.fi>
parents:
27
diff
changeset
|
28 |
sudo: exec using sudo |
5
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
29 |
|
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
30 |
Doesn't give any data on stdin, and keeps process stderr. |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
31 |
Returns stdout. |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
32 |
""" |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
33 |
|
68
adc190def3b1
pvl.backup.invoke: implement sudo=True to exec via sudo
Tero Marttila <terom@paivola.fi>
parents:
27
diff
changeset
|
34 |
log.debug("{sudo}{cmd} {args}".format(sudo=('sudo ' if sudo else ''), cmd=cmd, args=' '.join(args))) |
5
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
35 |
|
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
36 |
if data is False : |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
37 |
# keep process stdin/out |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
38 |
io = None |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
39 |
else : |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
40 |
io = subprocess.PIPE |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
41 |
|
68
adc190def3b1
pvl.backup.invoke: implement sudo=True to exec via sudo
Tero Marttila <terom@paivola.fi>
parents:
27
diff
changeset
|
42 |
args = [cmd] + args |
adc190def3b1
pvl.backup.invoke: implement sudo=True to exec via sudo
Tero Marttila <terom@paivola.fi>
parents:
27
diff
changeset
|
43 |
|
adc190def3b1
pvl.backup.invoke: implement sudo=True to exec via sudo
Tero Marttila <terom@paivola.fi>
parents:
27
diff
changeset
|
44 |
if sudo : |
adc190def3b1
pvl.backup.invoke: implement sudo=True to exec via sudo
Tero Marttila <terom@paivola.fi>
parents:
27
diff
changeset
|
45 |
args = [SUDO] + args |
adc190def3b1
pvl.backup.invoke: implement sudo=True to exec via sudo
Tero Marttila <terom@paivola.fi>
parents:
27
diff
changeset
|
46 |
|
adc190def3b1
pvl.backup.invoke: implement sudo=True to exec via sudo
Tero Marttila <terom@paivola.fi>
parents:
27
diff
changeset
|
47 |
p = subprocess.Popen(args, stdin=io, stdout=io) |
5
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
48 |
|
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
49 |
# get output |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
50 |
stdout, stderr = p.communicate(input=data) |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
51 |
|
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
52 |
if p.returncode : |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
53 |
# failed |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
54 |
raise InvokeError(cmd, p.returncode) |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
55 |
|
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
56 |
return stdout |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
57 |
|
12
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
58 |
def process_opt (opt, value) : |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
59 |
""" |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
60 |
Mangle from python keyword-argument dict format to command-line option tuple format. |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
61 |
|
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
62 |
>>> process_opt('foo', True) |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
63 |
('--foo',) |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
64 |
>>> process_opt('foo', 2) |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
65 |
('--foo', '2') |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
66 |
>>> process_opt('foo', 'bar') |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
67 |
('--foo', 'bar') |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
68 |
>>> process_opt('foo_bar', 'asdf') |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
69 |
('--foo-bar', 'asdf') |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
70 |
|
27
689407a261c3
invoke: change process_opt behaviour to omit all bool(...) == False options, including empty strings (fixes mount --options use)
Tero Marttila <terom@paivola.fi>
parents:
13
diff
changeset
|
71 |
# empty |
689407a261c3
invoke: change process_opt behaviour to omit all bool(...) == False options, including empty strings (fixes mount --options use)
Tero Marttila <terom@paivola.fi>
parents:
13
diff
changeset
|
72 |
>>> process_opt('foo', False) |
689407a261c3
invoke: change process_opt behaviour to omit all bool(...) == False options, including empty strings (fixes mount --options use)
Tero Marttila <terom@paivola.fi>
parents:
13
diff
changeset
|
73 |
() |
689407a261c3
invoke: change process_opt behaviour to omit all bool(...) == False options, including empty strings (fixes mount --options use)
Tero Marttila <terom@paivola.fi>
parents:
13
diff
changeset
|
74 |
>>> process_opt('foo', None) |
689407a261c3
invoke: change process_opt behaviour to omit all bool(...) == False options, including empty strings (fixes mount --options use)
Tero Marttila <terom@paivola.fi>
parents:
13
diff
changeset
|
75 |
() |
12
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
76 |
>>> process_opt('bar', '') |
27
689407a261c3
invoke: change process_opt behaviour to omit all bool(...) == False options, including empty strings (fixes mount --options use)
Tero Marttila <terom@paivola.fi>
parents:
13
diff
changeset
|
77 |
() |
12
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
78 |
|
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
79 |
Returns a tuple of argv items. |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
80 |
""" |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
81 |
|
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
82 |
# mangle opt |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
83 |
opt = '--' + opt.replace('_', '-') |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
84 |
|
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
85 |
if value is True : |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
86 |
# flag opt |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
87 |
return (opt, ) |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
88 |
|
27
689407a261c3
invoke: change process_opt behaviour to omit all bool(...) == False options, including empty strings (fixes mount --options use)
Tero Marttila <terom@paivola.fi>
parents:
13
diff
changeset
|
89 |
elif not value : |
12
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
90 |
# flag opt / omit |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
91 |
return ( ) |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
92 |
|
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
93 |
else : |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
94 |
# as-is |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
95 |
return (opt, str(value)) |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
96 |
|
5
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
97 |
def optargs (*args, **kwargs) : |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
98 |
""" |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
99 |
Convert args/options into command-line format |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
100 |
""" |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
101 |
|
12
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
102 |
## opts |
5
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
103 |
# process |
12
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
104 |
opts = [process_opt(opt, value) for opt, value in kwargs.iteritems()] |
5
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
105 |
|
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
106 |
# flatten |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
107 |
opts = [str(opt_part) for opt_parts in opts for opt_part in opt_parts if opt_part] |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
108 |
|
12
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
109 |
## args |
5
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
110 |
args = [str(arg) for arg in args if arg] |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
111 |
|
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
112 |
return opts + args |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
113 |
|
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
114 |
def command (cmd, *args, **opts) : |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
115 |
""" |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
116 |
Invoke a command with options/arguments, given via Python arguments/keyword arguments. |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
117 |
|
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
118 |
Return stdout. |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
119 |
""" |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
120 |
|
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
121 |
log.debug("{cmd} {opts} {args}".format(cmd=cmd, args=args, opts=opts)) |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
122 |
|
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
123 |
# invoke |
23371d26fdd0
split up into pvl.backup package
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
124 |
return invoke(cmd, optargs(*args, **opts)) |
12
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
125 |
|
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
126 |
if __name__ == '__main__': |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
127 |
import doctest |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
128 |
doctest.testmod() |
fbfdde7326f4
rsync-snapshot: manage --link-dest'd interval snapshots
Tero Marttila <terom@paivola.fi>
parents:
5
diff
changeset
|
129 |