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