~brianlbaird/charms/trusty/pcrf/trunk

« back to all changes in this revision

Viewing changes to deps/layer/layer-docker/reactive/docker.py

  • Committer: brian baird
  • Date: 2016-08-24 18:05:17 UTC
  • Revision ID: brianlbaird@gmail.com-20160824180517-uyp6100mfwuj6les
dt demo

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import os
 
2
from shlex import split
 
3
from subprocess import check_call
 
4
from subprocess import check_output
 
5
 
 
6
from charmhelpers.core.hookenv import status_set
 
7
from charmhelpers.core.hookenv import config
 
8
from charmhelpers.core.host import lsb_release
 
9
from charmhelpers.core.host import service_restart
 
10
from charmhelpers.core.templating import render
 
11
from charmhelpers.fetch import apt_install
 
12
from charmhelpers.fetch import apt_update
 
13
 
 
14
from charms.reactive import remove_state
 
15
from charms.reactive import set_state
 
16
from charms.reactive import when
 
17
from charms.reactive import when_any
 
18
from charms.reactive import when_not
 
19
 
 
20
from charms.docker import DockerOpts
 
21
 
 
22
from charms import layer
 
23
 
 
24
# 2 Major events are emitted from this layer.
 
25
#
 
26
# `docker.ready` is an event intended to signal other layers that need to
 
27
# plug into the plumbing to extend the docker daemon. Such as fire up a
 
28
# bootstrap docker daemon, or predependency fetch + dockeropt rendering
 
29
#
 
30
# `docker.available` means the docker daemon setup has settled and is prepared
 
31
# to run workloads. This is a broad state that has large implications should
 
32
# you decide to remove it. Production workloads can be lost if no restart flag
 
33
# is provided.
 
34
 
 
35
# Be sure you bind to it appropriately in your workload layer and
 
36
# react to the proper event.
 
37
 
 
38
 
 
39
@when_not('docker.ready')
 
40
def install():
 
41
    ''' Install the docker daemon, and supporting tooling '''
 
42
    # Often when building layer-docker based subordinates, you dont need to
 
43
    # incur the overhead of installing docker. This tuneable layer option
 
44
    # allows you to disable the exec of that install routine, and instead short
 
45
    # circuit immediately to docker.available, so you can charm away!
 
46
    layer_opts = layer.options('docker')
 
47
    if layer_opts['skip-install']:
 
48
        set_state('docker.available')
 
49
        set_state('docker.ready')
 
50
        return
 
51
 
 
52
    status_set('maintenance', 'Installing AUFS and other tools')
 
53
    kernel_release = check_output(['uname', '-r']).rstrip()
 
54
    packages = [
 
55
        'aufs-tools',
 
56
        'git',
 
57
        'linux-image-extra-{0}'.format(kernel_release),
 
58
    ]
 
59
    apt_update()
 
60
    apt_install(packages)
 
61
    # Install docker-engine from apt.
 
62
    install_from_apt()
 
63
 
 
64
    opts = DockerOpts()
 
65
    render('docker.defaults', '/etc/default/docker', {'opts': opts.to_s()})
 
66
    render('docker.systemd', '/lib/systemd/system/docker.service', config())
 
67
    reload_system_daemons()
 
68
 
 
69
    status_set('active', 'Docker installed, cycling for extensions')
 
70
    set_state('docker.ready')
 
71
 
 
72
    # Make with the adding of the users to the groups
 
73
    check_call(['usermod', '-aG', 'docker', 'ubuntu'])
 
74
 
 
75
 
 
76
@when_any('config.http_proxy.changed', 'config.https_proxy.changed')
 
77
def restart_docker():
 
78
    set_state('docker.restart')
 
79
 
 
80
 
 
81
def install_from_apt():
 
82
    ''' Install docker from the apt repository. This is a pyton adaptation of
 
83
    the shell script found at https://get.docker.com/ '''
 
84
    status_set('maintenance', 'Installing docker-engine from apt')
 
85
    keyserver = 'hkp://p80.pool.sks-keyservers.net:80'
 
86
    key = '58118E89F3A912897C070ADBF76221572C52609D'
 
87
    # Enter the server and key in the apt-key management tool.
 
88
    cmd = 'apt-key adv --keyserver {0} --recv-keys {1}'.format(keyserver, key)
 
89
    # "apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80
 
90
    # --recv-keys 58118E89F3A912897C070ADBF76221572C52609D"
 
91
    check_call(split(cmd))
 
92
    # The url to the server that contains the docker apt packages.
 
93
    apt_url = 'https://apt.dockerproject.org'
 
94
    # Get the package architecture (amd64), not the machine hardware (x86_64)
 
95
    arch = check_output(split('dpkg --print-architecture'))
 
96
    arch = arch.decode('utf-8').rstrip()
 
97
    # Get the lsb information as a dictionary.
 
98
    lsb = lsb_release()
 
99
    # Ubuntu must be lowercased.
 
100
    dist = lsb['DISTRIB_ID'].lower()
 
101
    # The codename for the release.
 
102
    code = lsb['DISTRIB_CODENAME']
 
103
    # repo can be: main, testing or experimental
 
104
    repo = 'main'
 
105
    # deb [arch=amd64] https://apt.dockerproject.org/repo ubuntu-xenial main
 
106
    deb = 'deb [arch={0}] {1}/repo {2}-{3} {4}'.format(
 
107
            arch, apt_url, dist, code, repo)
 
108
    # mkdir -p /etc/apt/sources.list.d
 
109
    if not os.path.isdir('/etc/apt/sources.list.d'):
 
110
        os.makedirs('/etc/apt/sources.list.d')
 
111
    # Write the docker source file to the apt sources.list.d directory.
 
112
    with(open('/etc/apt/sources.list.d/docker.list', 'w+')) as stream:
 
113
        stream.write(deb)
 
114
    apt_update(fatal=True)
 
115
    # apt-get install -y -q docker-engine
 
116
    apt_install(['docker-engine'], fatal=True)
 
117
 
 
118
 
 
119
@when('docker.ready')
 
120
@when_not('cgroups.modified')
 
121
def enable_grub_cgroups():
 
122
    cfg = config()
 
123
    if cfg.get('enable-cgroups'):
 
124
        check_call(['scripts/enable_grub_cgroups.sh'])
 
125
        set_state('cgroups.modified')
 
126
 
 
127
 
 
128
@when('docker.ready')
 
129
@when_not('docker.available')
 
130
def signal_workloads_start():
 
131
    ''' We can assume the pre-workload bits have completed now that docker.ready
 
132
    has been reacted to. Lets remove the predep work and continue on to being
 
133
    available '''
 
134
    status_set('active', 'Docker installed')
 
135
    set_state('docker.available')
 
136
 
 
137
 
 
138
@when('docker.restart')
 
139
def recycle_daemon():
 
140
    ''' Other layers should be able to trigger a daemon restart '''
 
141
    status_set('maintenance', 'Restarting docker daemon')
 
142
 
 
143
    # Re-render our docker daemon template at this time... because we're
 
144
    # restarting. And its nice to play nice with others. Isn't that nice?
 
145
    opts = DockerOpts()
 
146
    render('docker.defaults', '/etc/default/docker', {'opts': opts.to_s()})
 
147
    render('docker.systemd', '/lib/systemd/system/docker.service', config())
 
148
    reload_system_daemons()
 
149
    service_restart('docker')
 
150
    remove_state('docker.restart')
 
151
 
 
152
 
 
153
def reload_system_daemons():
 
154
    ''' Reload the system daemons from on-disk configuration changes '''
 
155
    command = ['systemctl', 'daemon-reload']
 
156
    check_call(command)