A class for representing a bitcoind or elementsd node. Wraps the process management, creation and deletion of datadirs, and RPC connectivity, into a simple object that will clean itself up on exit. The `cleanup_on_exit` parameter can be set to False to prevent the node from del
| 7 | import subprocess |
| 8 | |
| 9 | class Daemon(): |
| 10 | """ |
| 11 | A class for representing a bitcoind or elementsd node. |
| 12 | |
| 13 | Wraps the process management, creation and deletion of datadirs, and |
| 14 | RPC connectivity, into a simple object that will clean itself up on |
| 15 | exit. The `cleanup_on_exit` parameter can be set to False to prevent |
| 16 | the node from deleting its datadir on restart (and can be set by |
| 17 | passing --no-cleanup to the main program). |
| 18 | """ |
| 19 | |
| 20 | def __init__(self, name, daemon, path, conf_path, cleanup_on_exit = True): |
| 21 | self.name = name |
| 22 | self.daemon = daemon |
| 23 | self.conf_path = path |
| 24 | self.path = path |
| 25 | self.cleanup_on_exit = cleanup_on_exit |
| 26 | self.conf_path = conf_path |
| 27 | self.datadir_path = None |
| 28 | self.proc = None |
| 29 | self.rpc = None |
| 30 | |
| 31 | # Parse config |
| 32 | self.config = {} |
| 33 | with open(self.conf_path, encoding="utf8") as f: |
| 34 | for line in f: |
| 35 | if len(line) == 0 or line[0] == "#" or len(line.split("=")) != 2: |
| 36 | continue |
| 37 | self.config[line.split("=")[0]] = line.split("=")[1].strip() |
| 38 | |
| 39 | def shutdown(self): |
| 40 | if self.proc is not None: |
| 41 | print ("Shutting down %s" % self.name) |
| 42 | self.proc.terminate() |
| 43 | # FIXME determine why we need 30+ seconds to shut down with a tiny regtest chain |
| 44 | self.proc.wait(120) |
| 45 | self.proc = None |
| 46 | |
| 47 | if self.datadir_path is not None: |
| 48 | if self.cleanup_on_exit: |
| 49 | shutil.rmtree(self.datadir_path) |
| 50 | else: |
| 51 | print ("Leaving %s datadir at %s." % (self.name, self.datadir_path)) |
| 52 | |
| 53 | def start(self, ext_args = None, keep_datadir = False): |
| 54 | if keep_datadir and self.datadir_path is not None: |
| 55 | temp = self.datadir_path |
| 56 | self.datadir_path = None |
| 57 | self.shutdown() |
| 58 | self.datadir_path = temp |
| 59 | else: |
| 60 | self.shutdown() |
| 61 | # Create datadir and copy config into place |
| 62 | self.datadir_path = tempfile.mkdtemp() |
| 63 | shutil.copyfile(self.conf_path, self.datadir_path + '/' + self.daemon + '.conf') |
| 64 | print("%s datadir: %s" % (self.name, self.datadir_path)) |
| 65 | |
| 66 | # Start process |
no outgoing calls
no test coverage detected