6 import logging |
6 import logging |
7 from subprocess import Popen, PIPE |
7 from subprocess import Popen, PIPE |
8 from config import settings, arglistify |
8 from config import settings, arglistify |
9 |
9 |
10 necessary_opts=['--log-json', '--progress'] |
10 necessary_opts=['--log-json', '--progress'] |
|
11 |
|
12 necessary_opts_for={ |
|
13 'create': ['--json'], |
|
14 'info': ['--json'], |
|
15 'list': ['--json'], |
|
16 } |
11 |
17 |
12 class BorgInstance: |
18 class BorgInstance: |
13 def __init__(self, operation, archive_or_repository, args, argsl): |
19 def __init__(self, operation, archive_or_repository, args, argsl): |
14 self.operation=operation; |
20 self.operation=operation; |
15 self.args=args; |
21 self.args=args; |
22 [self.operation]) |
28 [self.operation]) |
23 tmp1=self.operation+'_parameters' |
29 tmp1=self.operation+'_parameters' |
24 if tmp1 in settings['borg']: |
30 if tmp1 in settings['borg']: |
25 cmd=cmd+arglistify(settings['borg'][tmp1]) |
31 cmd=cmd+arglistify(settings['borg'][tmp1]) |
26 |
32 |
|
33 if self.operation in necessary_opts_for: |
|
34 cmd=cmd+necessary_opts_for[self.operation] |
|
35 |
27 return cmd+arglistify(self.args)+[self.archive_or_repository]+self.argsl |
36 return cmd+arglistify(self.args)+[self.archive_or_repository]+self.argsl |
28 |
37 |
29 def launch(self): |
38 def launch(self): |
30 # Borg prints json to stderr, so pipe it |
|
31 cmd=self.construct_cmdline() |
39 cmd=self.construct_cmdline() |
32 |
40 |
33 logging.info('Launching ' + str(cmd)) |
41 logging.info('Launching ' + str(cmd)) |
34 |
42 |
35 self.proc=Popen(cmd, stderr=PIPE) |
43 self.proc=Popen(cmd, stdout=PIPE, stderr=PIPE) |
36 |
44 |
37 def read(self): |
45 def read_result(self): |
|
46 stream=self.proc.stdout |
|
47 line=stream.read(-1) |
|
48 if line==b'': |
|
49 logging.debug('Borg stdout pipe EOF?') |
|
50 return None |
|
51 |
38 try: |
52 try: |
39 line=self.proc.stderr.readline() |
53 return json.loads(line) |
|
54 except: |
|
55 logging.warning('JSON parse failed on: "%s"' % line) |
|
56 return None |
|
57 |
|
58 def read_log(self): |
|
59 stream=self.proc.stderr |
|
60 try: |
|
61 line=stream.readline() |
40 except err: |
62 except err: |
41 logging.info('Pipe read failed: %s' % str(err)) |
63 logging.debug('Pipe read failed: %s' % str(err)) |
42 |
64 |
43 return {'type': 'exception', 'exception': err} |
65 return {'type': 'exception', 'exception': err} |
44 |
66 |
45 if line==b'': |
67 if line==b'': |
46 |
68 |
47 logging.info('Pipe EOF?') |
69 logging.debug('Borg stderr pipe EOF?') |
48 |
70 |
49 return None |
71 return None |
50 |
72 |
51 try: |
73 try: |
52 res=json.loads(line) |
74 res=json.loads(line) |
53 if 'type' not in res: |
75 if 'type' not in res: |
54 res['type']='UNKNOWN' |
76 res['type']='UNKNOWN' |
55 return res |
77 return res |
56 except: |
78 except: |
57 logging.warning('JSON parse failed on: "%s"' % line) |
79 logging.debug('JSON parse failed on: "%s"' % line) |
58 |
80 |
59 errmsg=line |
81 errmsg=line |
60 for line in iter(self.proc.stderr.readline, b''): |
82 for line in iter(stream.readline, b''): |
61 errmsg=errmsg+line |
83 errmsg=errmsg+line |
62 |
84 |
63 return {'type': 'unparsed_error', 'message': str(errmsg)} |
85 return {'type': 'unparsed_error', 'message': str(errmsg)} |
64 |
86 |
65 def terminate(self): |
87 def terminate(self): |