larigira.py 3.1 KB

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