coin_daemon_control.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. #!/usr/bin/env python3
  2. #
  3. # mmgen = Multi-Mode GENerator, a command-line cryptocurrency wallet
  4. # Copyright (C)2013-2023 The MMGen Project <mmgen@tuta.io>
  5. # Licensed under the GNU General Public License, Version 3:
  6. # https://www.gnu.org/licenses
  7. # Public project repositories:
  8. # https://github.com/mmgen/mmgen
  9. # https://gitlab.com/mmgen/mmgen
  10. """
  11. test.include.coin_daemon_control: Start and stop daemons for the MMGen test suite
  12. """
  13. import include.test_init
  14. from mmgen.cfg import Config,gc
  15. from mmgen.util import msg,die,oneshot_warning,async_run
  16. from mmgen.protocol import init_proto
  17. xmr_wallet_network_ids = {
  18. 'xmrw': 'mainnet',
  19. 'xmrw_tn': 'testnet'
  20. }
  21. action = gc.prog_name.split('-')[0]
  22. opts_data = {
  23. 'sets': [('debug',True,'verbose',True)],
  24. 'text': {
  25. 'desc': f'{action.capitalize()} coin or wallet daemons for the MMGen test suite',
  26. 'usage':'[opts] <network IDs>',
  27. 'options': """
  28. -h, --help Print this help message
  29. --, --longhelp Print help message for long options (common options)
  30. -D, --debug Produce debugging output (implies --verbose)
  31. -d, --datadir= Override the default datadir
  32. -i, --daemon-ids Print all known daemon IDs
  33. -m, --mainnet-only Perform operations for mainnet daemons only
  34. -n, --no-daemonize Don't fork daemon to background
  35. -p, --port-shift= Shift the RPC port by this number
  36. -s, --get-state Get the state of the daemon(s) and exit
  37. -t, --testing Testing mode. Print commands but don't execute them
  38. -q, --quiet Produce quieter output
  39. -u, --usermode Run the daemon in user (non test-suite) mode
  40. -v, --verbose Produce more verbose output
  41. -V, --print-version Print version strings from exec’ed daemons (not RPC)
  42. -W, --no-wait Don't wait for daemons to change state before exiting
  43. """,
  44. 'notes': """
  45. Valid network IDs: {nid}, {xmrw_nid}, all, no_xmr
  46. """
  47. },
  48. 'code': {
  49. 'options': lambda s: s.format(a=action.capitalize(),pn=gc.prog_name),
  50. 'notes': lambda s,help_notes: s.format(
  51. nid = help_notes('coin_daemon_network_ids'),
  52. xmrw_nid = ', '.join(xmr_wallet_network_ids),
  53. )
  54. }
  55. }
  56. cfg = Config(opts_data=opts_data)
  57. from mmgen.daemon import CoinDaemon
  58. class warn_missing_exec(oneshot_warning):
  59. color = 'nocolor'
  60. message = 'daemon executable {!r} not found on this system!'
  61. def run(network_id=None,proto=None,daemon_id=None,missing_exec_ok=False):
  62. if network_id in xmr_wallet_network_ids:
  63. from mmgen.proto.xmr.daemon import MoneroWalletDaemon
  64. d = MoneroWalletDaemon(
  65. cfg = cfg,
  66. proto = init_proto( cfg, coin='XMR', network=xmr_wallet_network_ids[network_id] ),
  67. user = 'test',
  68. passwd = 'test passwd',
  69. test_suite = True,
  70. monerod_addr = None,
  71. trust_monerod = True,
  72. test_monerod = False,
  73. opts = ['no_daemonize'] if cfg.no_daemonize else None )
  74. else:
  75. d = CoinDaemon(
  76. cfg,
  77. network_id = network_id,
  78. proto = proto,
  79. test_suite = not cfg.usermode,
  80. opts = ['no_daemonize'] if cfg.no_daemonize else None,
  81. port_shift = int(cfg.port_shift or 0),
  82. datadir = cfg.datadir,
  83. daemon_id = daemon_id )
  84. if cfg.mainnet_only and d.network != 'mainnet':
  85. return
  86. d.debug = d.debug or cfg.debug
  87. d.wait = not cfg.no_wait
  88. if missing_exec_ok:
  89. try:
  90. d.get_exec_version_str()
  91. except Exception as e:
  92. if not cfg.quiet:
  93. msg(str(e))
  94. warn_missing_exec( div=d.exec_fn, fmt_args=(d.exec_fn,) )
  95. return
  96. if cfg.print_version:
  97. msg('{:16} {}'.format( d.exec_fn+':', d.get_exec_version_str() ))
  98. elif cfg.get_state:
  99. print(d.state_msg())
  100. elif cfg.testing:
  101. for cmd in d.start_cmds if action == 'start' else [d.stop_cmd]:
  102. print(' '.join(cmd))
  103. else:
  104. if action == 'stop' and hasattr(d,'rpc'):
  105. async_run(d.rpc.stop_daemon(quiet=cfg.quiet))
  106. else:
  107. d.cmd(action,quiet=cfg.quiet)
  108. if cfg.daemon_ids:
  109. print('\n'.join(CoinDaemon.all_daemon_ids()))
  110. elif 'all' in cfg._args or 'no_xmr' in cfg._args:
  111. if len(cfg._args) != 1:
  112. die(1,"'all' or 'no_xmr' must be the sole argument")
  113. for coin in CoinDaemon.coins:
  114. if coin == 'XMR' and cfg._args[0] == 'no_xmr':
  115. continue
  116. for daemon_id in CoinDaemon.get_daemon_ids(cfg,coin):
  117. for network in CoinDaemon.get_daemon(cfg,coin,daemon_id).networks:
  118. run(
  119. proto = init_proto( cfg, coin=coin, network=network ),
  120. daemon_id = daemon_id,
  121. missing_exec_ok = True )
  122. else:
  123. ids = cfg._args
  124. network_ids = CoinDaemon.get_network_ids(cfg)
  125. if not ids:
  126. cfg._opts.usage()
  127. for i in ids:
  128. if i not in network_ids + list(xmr_wallet_network_ids):
  129. die(1,f'{i!r}: invalid network ID')
  130. for network_id in ids:
  131. run(network_id=network_id.lower())