main.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. """
  2. This module is for the main application logic
  3. """
  4. from __future__ import print_function
  5. import json
  6. import logging
  7. import logging.config
  8. import os
  9. import signal
  10. import subprocess
  11. import sys
  12. import tempfile
  13. from time import sleep
  14. import gevent
  15. from gevent import monkey
  16. from gevent.pywsgi import WSGIServer
  17. from larigira.config import get_conf
  18. from larigira.mpc import Controller, get_mpd_client
  19. from larigira.rpc import create_app
  20. monkey.patch_all(subprocess=True)
  21. def on_main_crash(*args, **kwargs):
  22. print('A crash occurred in "main" greenlet. Aborting...')
  23. sys.exit(1)
  24. class Larigira(object):
  25. def __init__(self):
  26. self.log = logging.getLogger("larigira")
  27. self.conf = get_conf()
  28. self.controller = Controller(self.conf)
  29. self.controller.link_exception(on_main_crash)
  30. self.http_server = WSGIServer(
  31. (self.conf["HTTP_ADDRESS"], int(self.conf["HTTP_PORT"])),
  32. create_app(self.controller.q, self),
  33. )
  34. def start(self):
  35. self.controller.start()
  36. self.http_server.start()
  37. def sd_notify(ready=False, status=None):
  38. args = ["systemd-notify"]
  39. if ready:
  40. args.append("--ready")
  41. if status is not None:
  42. args.append("--status")
  43. args.append(status)
  44. try:
  45. subprocess.check_call(args)
  46. except:
  47. pass
  48. def main():
  49. logging.addLevelName(9, "DEBUGV")
  50. if get_conf()["LOG_CONFIG"]:
  51. logging.config.fileConfig(
  52. get_conf()["LOG_CONFIG"], disable_existing_loggers=True
  53. )
  54. else:
  55. log_format = (
  56. "%(asctime)s|%(levelname)s[%(name)s:%(lineno)d] %(message)s"
  57. )
  58. logging.basicConfig(
  59. level="DEBUGV" if get_conf()["DEBUG"] else logging.INFO,
  60. format=log_format,
  61. datefmt="%H:%M:%S",
  62. )
  63. def debugv(self, message, *args, **kws):
  64. if self.isEnabledFor(9):
  65. self._log(9, message, args, **kws)
  66. logging.Logger.debugv = debugv
  67. logging.debug(
  68. "Starting larigira with this conf:\n%s",
  69. json.dumps(get_conf(), indent=2),
  70. )
  71. if get_conf()["UMASK"]:
  72. umask = int(get_conf()["UMASK"], base=8)
  73. logging.debug(
  74. "Setting umask %s (decimal: %d)", get_conf()["UMASK"], umask
  75. )
  76. os.umask(umask)
  77. tempfile.tempdir = os.environ["TMPDIR"] = os.path.join(
  78. os.getenv("TMPDIR", "/tmp"), "larigira.%d" % os.getuid()
  79. )
  80. if not os.path.isdir(os.environ["TMPDIR"]):
  81. os.makedirs(os.environ["TMPDIR"])
  82. if get_conf()["MPD_WAIT_START"]:
  83. while True:
  84. try:
  85. get_mpd_client(get_conf())
  86. except Exception as exc:
  87. print("exc", exc, file=sys.stderr)
  88. logging.debug(
  89. "Could not connect to MPD at (%s,%s), waiting",
  90. get_conf()["MPD_HOST"],
  91. get_conf()["MPD_PORT"],
  92. )
  93. sd_notify(status="Waiting MPD connection")
  94. sleep(int(get_conf()["MPD_WAIT_START_RETRYSECS"]))
  95. else:
  96. logging.info("MPD ready!")
  97. sd_notify(ready=True, status="Ready")
  98. break
  99. larigira = Larigira()
  100. larigira.start()
  101. def sig(*args):
  102. print("invoked sig", args)
  103. larigira.controller.q.put(dict(kind="signal", args=args))
  104. for signum in (signal.SIGHUP, signal.SIGALRM):
  105. gevent.signal(signum, sig, signum)
  106. gevent.wait()
  107. if __name__ == "__main__":
  108. main()