PageRenderTime 251ms CodeModel.GetById 70ms app.highlight 102ms RepoModel.GetById 69ms app.codeStats 1ms

/silverlining/commands/update.py

https://bitbucket.org/ianb/silverlining/
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')