| 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 |