PageRenderTime 11ms CodeModel.GetById 1ms RepoModel.GetById 1ms app.codeStats 0ms

/silverlining/commands/update.py

https://bitbucket.org/ianb/silverlining/
Python | 99 lines | 94 code | 4 blank | 1 comment | 14 complexity | d7ceb0d3749db891ff1828ebb500ee59 MD5 | raw file
Possible License(s): GPL-2.0
  1. """Update/deploy an application"""
  2. import re
  3. import os
  4. import socket
  5. from cmdutils import CommandError
  6. import virtualenv
  7. from silverlining.etchosts import set_etc_hosts
  8. from silversupport.shell import ssh, run
  9. from silversupport.appconfig import AppConfig
  10. from silversupport import appdata
  11. _instance_name_re = re.compile(r'instance_name="(.*?)"')
  12. def command_update(config):
  13. if not os.path.exists(config.args.dir):
  14. raise CommandError(
  15. "No directory in %s" % config.args.dir)
  16. config.logger.info('Fixing up .pth and .egg-info files')
  17. virtualenv.logger = config.logger
  18. config.logger.indent += 2
  19. config.logger.level_adjust += -1
  20. app = AppConfig(os.path.join(config.args.dir, 'app.ini'),
  21. app_name=config.args.name or None)
  22. if not config.args.location:
  23. if app.default_location:
  24. config.args.location = app.default_location
  25. else:
  26. config.args.location = config.node_hostname
  27. if config.args.config:
  28. check_config_in_subprocess(app, config.args.config, config.logger)
  29. try:
  30. virtualenv.fixup_pth_and_egg_link(
  31. config.args.dir,
  32. [os.path.join(config.args.dir, 'lib', 'python2.6'),
  33. os.path.join(config.args.dir, 'lib', 'python2.6', 'site-packages'),
  34. os.path.join(config.args.dir, 'lib', 'python')])
  35. finally:
  36. config.logger.indent -= 2
  37. config.logger.level_adjust -= -1
  38. if not config.args.node:
  39. from silversupport.appdata import normalize_location
  40. config.args.node = normalize_location(config.args.location)[0]
  41. stdout, stderr, returncode = ssh(
  42. 'www-mgr', config.node_hostname,
  43. '/usr/local/share/silverlining/mgr-scripts/prepare-new-instance.py %s' % app.app_name,
  44. capture_stdout=True, capture_stderr=True)
  45. match = _instance_name_re.search(stdout)
  46. if not match:
  47. config.logger.fatal("Did not get the new instance_name from prepare-new-instance.py")
  48. config.logger.fatal("Output: %s (stderr: %s)" % (stdout, stderr))
  49. raise Exception("Bad instance_name output")
  50. instance_name = match.group(1)
  51. assert instance_name.startswith(app.app_name), instance_name
  52. app.sync('www-mgr@%s' % config.node_hostname, instance_name)
  53. if config.args.config:
  54. config.logger.info('Synchronizing configuration %s to server' % config.args.config)
  55. app.sync_config('www-mgr@%s' % config.node_hostname, os.path.abspath(config.args.config))
  56. if config.args.clear:
  57. clear_option = '--clear'
  58. else:
  59. clear_option = ''
  60. ssh('root', config.node_hostname,
  61. 'find /var/www/%(instance_name)s -name "*.pyc" -delete; '
  62. 'python -m compileall -q /var/www/%(instance_name)s; '
  63. '/usr/local/share/silverlining/mgr-scripts/update-service.py %(instance_name)s %(clear_option)s'
  64. % dict(instance_name=instance_name,
  65. clear_option=clear_option))
  66. if config.args.debug_single_process:
  67. debug_single_process = '--debug-single-process'
  68. else:
  69. debug_single_process = ''
  70. ssh('www-mgr', config.node_hostname,
  71. '/usr/local/share/silverlining/mgr-scripts/update-appdata.py %(instance_name)s %(debug_single_process)s %(location)s; '
  72. 'sudo -H -u www-data /usr/local/share/silverlining/mgr-scripts/internal-request.py --update %(instance_name)s %(location)s; '
  73. 'sudo -H -u www-data pkill -INT -f -u www-data wsgi; '
  74. % dict(instance_name=instance_name,
  75. debug_single_process=debug_single_process,
  76. location=config.args.location),
  77. )
  78. if config.args.update_etc_hosts:
  79. ip = socket.gethostbyname(config.node_hostname)
  80. hostname = appdata.normalize_location(config.args.location)[0]
  81. set_etc_hosts(config, [hostname,
  82. 'prev.' + hostname], ip)
  83. def check_config_in_subprocess(app, config, logger):
  84. logger.notify('Checking configuration.')
  85. fn = os.path.join(os.path.dirname(__file__), 'update-check-config.py')
  86. exe = os.path.join(app.app_dir, 'bin/python')
  87. if not os.path.exists(exe):
  88. exe = 'python2.6'
  89. stdout, stderr, returncode = run([exe, fn, app.app_dir, config])
  90. if returncode:
  91. raise CommandError('Configuration checking failed')