1 # |
1 # |
2 # Borgend borg launcher / processor |
2 # Borgend borg launcher / processor |
3 # |
3 # |
4 |
4 |
5 import json |
5 import json |
|
6 import logging |
6 from subprocess import Popen, PIPE |
7 from subprocess import Popen, PIPE |
7 from config import settings, arglistify |
8 from config import settings, arglistify |
8 |
9 |
|
10 necessary_opts=['--log-json', '--progress'] |
|
11 |
9 class BorgInstance: |
12 class BorgInstance: |
10 |
|
11 def __init__(self, operation, archive_or_repository, args, argsl): |
13 def __init__(self, operation, archive_or_repository, args, argsl): |
12 self.operation=operation; |
14 self.operation=operation; |
13 self.args=args; |
15 self.args=args; |
14 self.archive_or_repository=archive_or_repository; |
16 self.archive_or_repository=archive_or_repository; |
15 self.argsl=argsl; |
17 self.argsl=argsl; |
16 |
18 |
17 def construct_cmdline(self): |
19 def construct_cmdline(self): |
18 cmd=([settings['borg']['executable'], '--log-json']+ |
20 cmd=([settings['borg']['executable']]+necessary_opts+ |
19 arglistify(settings['borg']['common_parameters'])+ |
21 arglistify(settings['borg']['common_parameters'])+ |
20 [self.operation]) |
22 [self.operation]) |
21 tmp1=self.operation+'_parameters' |
23 tmp1=self.operation+'_parameters' |
22 if tmp1 in settings['borg']: |
24 if tmp1 in settings['borg']: |
23 cmd=cmd+arglistify(settings['borg'][tmp1]) |
25 cmd=cmd+arglistify(settings['borg'][tmp1]) |
24 cmd=cmd+arglistify(self.args)+[self.archive_or_repository]+self.argsl |
26 |
25 print(cmd) |
27 return cmd+arglistify(self.args)+[self.archive_or_repository]+self.argsl |
26 return cmd |
|
27 |
28 |
28 def launch(self): |
29 def launch(self): |
29 # What to do with stderr? Is it needed? |
30 # Borg prints json to stderr, so pipe it |
30 self.proc=Popen(self.construct_cmdline(), stdout=PIPE, stderr=PIPE) |
31 cmd=self.construct_cmdline() |
|
32 |
|
33 logging.info('Launching ' + str(cmd)) |
|
34 |
|
35 self.proc=Popen(cmd, stderr=PIPE) |
31 |
36 |
32 def read(self): |
37 def read(self): |
33 line=self.proc.stdout.readline() |
38 try: |
|
39 line=self.proc.stderr.readline() |
|
40 except err: |
|
41 logging.info('Pipe read failed: %s' % str(err)) |
|
42 |
|
43 return {'type': 'exception', 'exception': err} |
|
44 |
34 if line==b'': |
45 if line==b'': |
35 line=self.proc.stderr.readline() |
|
36 if line==b'': |
|
37 return None |
|
38 print('EEE'+str(line)) |
|
39 return 'error' |
|
40 else: |
|
41 print('###' + str(line)) |
|
42 # # What to do on error? stderr? |
|
43 status=json.loads(line) |
|
44 return status |
|
45 |
46 |
46 # for line in iter(stream.readline, b''): |
47 logging.info('Pipe EOF?') |
47 # status=json.loads(line) |
|
48 # queue.put({'identifier': instance.identifier, |
|
49 # 'operation': instance.operation, |
|
50 # 'status': status}) |
|
51 # out.close() |
|
52 |
48 |
53 # def read_output(): |
49 return None |
54 # try: |
|
55 # obj=self.queue.get_nowait() |
|
56 # except Empty: |
|
57 # obj=Empty |
|
58 # return obj |
|
59 |
50 |
|
51 try: |
|
52 return json.loads(line) |
|
53 except: |
|
54 logging.warning('JSON parse failed on: "%s"' % line) |
60 |
55 |
|
56 errmsg=line |
|
57 for line in iter(self.proc.stderr.readline, b''): |
|
58 errmsg=errmsg+line |
61 |
59 |
|
60 return {'type': 'unparsed_error', 'message': str(errmsg)} |
62 |
61 |
|
62 def terminate(self): |
|
63 self.proc.terminate() |
|
64 |
|
65 def wait(self): |
|
66 return self.proc.wait() is not None |
|
67 |
|
68 def has_terminated(self): |
|
69 return self.proc.poll() is not None |
|
70 |