summaryrefslogtreecommitdiff
path: root/ybd/deployment.py
blob: 6afafe187bb2f5b0d2eba5eb23580bc0e969c51c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# Copyright (C) 2014-2016  Codethink Limited
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# =*= License: GPL-2 =*=

import os
from subprocess import call
import json
import shutil
import app
import cache
import sandbox


def deploy(target):
    '''Deploy a cluster definition.'''
    arch = app.config['arch']
    for system in target.get('systems', []):
        if app.defs.get(system).get('arch', arch) == arch:
            with app.timer(system, 'deployment'):
                deploy_system(system)


def deploy_system(system_spec, parent_location=''):
    '''Deploy a system and subsystems recursively.

    Takes a system spec (i.e. an entry in the "systems" list in a cluster
    definition), and optionally a path to a parent system tree. If
    `parent_location` is given then the `location` given in the cluster
    definition for the subsystem is appended to `parent_location`, with
    the result being used as the location for the deployment extensions.

    '''
    system = app.defs.get(system_spec['path'])
    if not cache.get_cache(system):
        app.log('DEPLOY', 'System is not built, cannot deploy:\n', system,
                exit=True)
    deploy_defaults = system_spec.get('deploy-defaults')

    with sandbox.setup(system):
        # Clean up directories not required for deployment.
        shutil.rmtree(system['checkout'])
        shutil.rmtree(system['install'])

        app.log(system, 'Extracting system artifact into', system['sandbox'])
        with open(cache.get_cache(system), 'r') as artifact:
            call(['tar', 'x', '--directory', system['sandbox']],
                 stdin=artifact)

        for subsystem in system_spec.get('subsystems', []):
            if deploy_defaults:
                subsystem = dict(deploy_defaults.items() + subsystem.items())
            deploy_system(subsystem, parent_location=system['sandbox'])

        for name, deployment in system_spec.get('deploy', {}).iteritems():
            method = deployment.get('type') or deployment.get('upgrade-type')
            method = os.path.basename(method)
            if deploy_defaults:
                deployment = dict(deploy_defaults.items() + deployment.items())
            do_deployment_manifest(system, deployment)
            if parent_location:
                for l in ['location', 'upgrade-location']:
                    if l in deployment:
                        dn = deployment[l].lstrip('/')
                        deployment[l] = os.path.join(parent_location, dn)
            try:
                sandbox.run_extension(system, deployment, 'check', method)
            except KeyError:
                app.log(system, "Couldn't find a check extension for", method)

            for ext in system.get('configuration-extensions', []):
                sandbox.run_extension(system, deployment, 'configure',
                                      os.path.basename(ext))
            os.chmod(system['sandbox'], 0o755)
            sandbox.run_extension(system, deployment, 'write', method)


def do_deployment_manifest(system, configuration):
    app.log(system, "Creating deployment manifest in", system['sandbox'])
    data = {'configuration': configuration}
    metafile = os.path.join(system['sandbox'], 'baserock', 'deployment.meta')
    with app.chdir(system['sandbox']), open(metafile, "w") as f:
        json.dump(data, f, indent=4, sort_keys=True, encoding='unicode-escape')
        f.flush()