/silverlining/commands/update.py
Python | 99 lines | 94 code | 4 blank | 1 comment | 14 complexity | d7ceb0d3749db891ff1828ebb500ee59 MD5 | raw file
Possible License(s): GPL-2.0
- """Update/deploy an application"""
- import re
- import os
- import socket
- from cmdutils import CommandError
- import virtualenv
- from silverlining.etchosts import set_etc_hosts
- from silversupport.shell import ssh, run
- from silversupport.appconfig import AppConfig
- from silversupport import appdata
- _instance_name_re = re.compile(r'instance_name="(.*?)"')
- def command_update(config):
- if not os.path.exists(config.args.dir):
- raise CommandError(
- "No directory in %s" % config.args.dir)
- config.logger.info('Fixing up .pth and .egg-info files')
- virtualenv.logger = config.logger
- config.logger.indent += 2
- config.logger.level_adjust += -1
- app = AppConfig(os.path.join(config.args.dir, 'app.ini'),
- app_name=config.args.name or None)
- if not config.args.location:
- if app.default_location:
- config.args.location = app.default_location
- else:
- config.args.location = config.node_hostname
- if config.args.config:
- check_config_in_subprocess(app, config.args.config, config.logger)
- try:
- virtualenv.fixup_pth_and_egg_link(
- config.args.dir,
- [os.path.join(config.args.dir, 'lib', 'python2.6'),
- os.path.join(config.args.dir, 'lib', 'python2.6', 'site-packages'),
- os.path.join(config.args.dir, 'lib', 'python')])
- finally:
- config.logger.indent -= 2
- config.logger.level_adjust -= -1
- if not config.args.node:
- from silversupport.appdata import normalize_location
- config.args.node = normalize_location(config.args.location)[0]
- stdout, stderr, returncode = ssh(
- 'www-mgr', config.node_hostname,
- '/usr/local/share/silverlining/mgr-scripts/prepare-new-instance.py %s' % app.app_name,
- capture_stdout=True, capture_stderr=True)
- match = _instance_name_re.search(stdout)
- if not match:
- config.logger.fatal("Did not get the new instance_name from prepare-new-instance.py")
- config.logger.fatal("Output: %s (stderr: %s)" % (stdout, stderr))
- raise Exception("Bad instance_name output")
- instance_name = match.group(1)
- assert instance_name.startswith(app.app_name), instance_name
- app.sync('www-mgr@%s' % config.node_hostname, instance_name)
- if config.args.config:
- config.logger.info('Synchronizing configuration %s to server' % config.args.config)
- app.sync_config('www-mgr@%s' % config.node_hostname, os.path.abspath(config.args.config))
- if config.args.clear:
- clear_option = '--clear'
- else:
- clear_option = ''
- ssh('root', config.node_hostname,
- 'find /var/www/%(instance_name)s -name "*.pyc" -delete; '
- 'python -m compileall -q /var/www/%(instance_name)s; '
- '/usr/local/share/silverlining/mgr-scripts/update-service.py %(instance_name)s %(clear_option)s'
- % dict(instance_name=instance_name,
- clear_option=clear_option))
- if config.args.debug_single_process:
- debug_single_process = '--debug-single-process'
- else:
- debug_single_process = ''
- ssh('www-mgr', config.node_hostname,
- '/usr/local/share/silverlining/mgr-scripts/update-appdata.py %(instance_name)s %(debug_single_process)s %(location)s; '
- 'sudo -H -u www-data /usr/local/share/silverlining/mgr-scripts/internal-request.py --update %(instance_name)s %(location)s; '
- 'sudo -H -u www-data pkill -INT -f -u www-data wsgi; '
- % dict(instance_name=instance_name,
- debug_single_process=debug_single_process,
- location=config.args.location),
- )
- if config.args.update_etc_hosts:
- ip = socket.gethostbyname(config.node_hostname)
- hostname = appdata.normalize_location(config.args.location)[0]
- set_etc_hosts(config, [hostname,
- 'prev.' + hostname], ip)
- def check_config_in_subprocess(app, config, logger):
- logger.notify('Checking configuration.')
- fn = os.path.join(os.path.dirname(__file__), 'update-check-config.py')
- exe = os.path.join(app.app_dir, 'bin/python')
- if not os.path.exists(exe):
- exe = 'python2.6'
- stdout, stderr, returncode = run([exe, fn, app.app_dir, config])
- if returncode:
- raise CommandError('Configuration checking failed')