~freyes/charms/trusty/memcached/lp1636519

« back to all changes in this revision

Viewing changes to hooks/memcached_hooks.py

  • Committer: Jorge Niedbalski
  • Date: 2015-02-18 20:24:50 UTC
  • mfrom: (64.1.15 memcached)
  • Revision ID: jorge.niedbalski@canonical.com-20150218202450-k2kslavk9ic180x0
[niedbalski, r=freyes, billy-olsen] Adds replication support for memcacehd. Fixes bug LP: #1421660

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/env python
2
 
__author__ = 'Felipe Reyes <felipe.reyes@canonical.com>'
3
 
 
4
2
import re
5
3
import os
6
4
import shutil
7
5
import subprocess
8
6
import sys
 
7
import time
9
8
 
10
9
from charmhelpers.core.hookenv import (
11
10
    config,
25
24
    service_start,
26
25
    service_stop,
27
26
)
28
 
from charmhelpers.fetch import apt_install, apt_update
 
27
 
 
28
from charmhelpers.contrib.hahelpers.cluster import (
 
29
    oldest_peer,
 
30
    peer_units,
 
31
)
 
32
 
 
33
from charmhelpers.fetch import apt_install, apt_update, add_source
29
34
from charmhelpers.contrib.network import ufw
 
35
 
30
36
import memcached_utils
 
37
import replication
31
38
 
 
39
__author__ = 'Felipe Reyes <felipe.reyes@canonical.com>'
32
40
 
33
41
DOT = os.path.dirname(os.path.abspath(__file__))
34
42
ETC_DEFAULT_MEMCACHED = '/etc/default/memcached'
38
46
MEMCACHE_NAGIOS_PLUGIN = '/usr/local/lib/nagios/plugins/check_memcache.py'
39
47
RESTART_MAP = {ETC_MEMCACHED_CONF: ['memcached'],
40
48
               ETC_MUNIN_NODE_CONF: ['munin-node']}
 
49
 
41
50
hooks = Hooks()
42
51
 
43
52
 
47
56
 
48
57
@hooks.hook('install')
49
58
def install():
 
59
    enable_repcached = config('repcached')
 
60
 
 
61
    if enable_repcached:
 
62
        add_source(config('repcached_origin'))
 
63
 
50
64
    apt_update(fatal=True)
51
65
    apt_install(["memcached", "python-cheetah", "python-memcache"], fatal=True)
52
66
 
54
68
        f.write('ENABLE_MEMCACHED=yes\n')
55
69
 
56
70
    ufw.enable()
 
71
 
 
72
    if enable_repcached:
 
73
        ufw.service(config('repcached_port'), 'open')
 
74
 
57
75
    ufw.service('ssh', 'open')
58
76
 
59
77
 
67
85
    service_stop('memcached')
68
86
 
69
87
 
 
88
@hooks.hook('cluster-relation-joined')
 
89
def cluster_relation_joined():
 
90
 
 
91
    if not config('repcached'):
 
92
        return config_changed()
 
93
 
 
94
    peers = peer_units()
 
95
    if peers and not oldest_peer(peers):
 
96
        log("Delaying operation to oldest peer", level='INFO')
 
97
        return
 
98
 
 
99
    replica = replication.get_repcached_replica()
 
100
    if not replica:
 
101
        replica = replication.set_repcached_replica()
 
102
 
 
103
    master, replica = replica
 
104
    log("Setting replication with peer unit: %s" % replica, level="INFO")
 
105
    config_changed(replica=replica)
 
106
 
 
107
 
 
108
@hooks.hook('cluster-relation-changed')
 
109
def cluster_relation_changed():
 
110
 
 
111
    if not config('repcached'):
 
112
        return config_changed()
 
113
 
 
114
    peers = peer_units()
 
115
    if peers and oldest_peer(peers):
 
116
        log("Delaying operation to secondary peer", level='INFO')
 
117
        return
 
118
 
 
119
    retries = 0
 
120
    while retries < 3:
 
121
        log('Waiting for master memcached node to become available',
 
122
            level='INFO')
 
123
        secondary = relation_get('replica')
 
124
        try:
 
125
            if secondary == unit_get('private-address'):
 
126
                replication.store_replica(relation_get('master'), secondary)
 
127
                return config_changed(replica=relation_get('master'))
 
128
            elif secondary is None:
 
129
                raise AttributeError()
 
130
            else:
 
131
                msg = """This unit will be marked as failed because
 
132
                Repcached replication only can take place between two units.
 
133
                If you want to disable this set 'juju set repcached=false'"""
 
134
                log(msg, level='WARN')
 
135
                raise Exception(msg)
 
136
        except AttributeError:
 
137
            log("Master not yet available, waiting for %d secs" %
 
138
                replication.REPCACHED_MASTER_WAIT)
 
139
            time.sleep(replication.REPCACHED_MASTER_WAIT)
 
140
            retries += 1
 
141
 
 
142
 
70
143
@hooks.hook('cache-relation-joined')
71
144
def cache_relation_joined():
72
145
 
92
165
 
93
166
@hooks.hook('config-changed')
94
167
@restart_on_change(RESTART_MAP)
95
 
def config_changed():
 
168
def config_changed(replica=None):
96
169
    mem_size = config('size')
97
170
 
98
171
    if mem_size == 0:
100
173
        mem_size = int(re.findall(r'\d+', output.split('\n')[2])[1])
101
174
        mem_size = int(mem_size * 0.9)
102
175
 
 
176
    if config('repcached'):
 
177
        # If repcached was enabled after install, we need
 
178
        # to make sure to install the memcached package with replication
 
179
        # enabled.
 
180
        if not memcached_utils.dpkg_info_contains('memcached',
 
181
                                                  'version',
 
182
                                                  'repcache'):
 
183
            add_source(config('repcached_origin'))
 
184
            apt_update(fatal=True)
 
185
            apt_install(["memcached"], fatal=True)
 
186
 
 
187
        if not replica:
 
188
            replica = replication.get_current_replica()
 
189
 
 
190
    elif (
 
191
        config('repcached') and
 
192
        os.path.exists(replication.REPCACHED_REPLICA_FILE)
 
193
    ):
 
194
        log("Replication has been disabled, removing from this unit",
 
195
            level='INFO')
 
196
        ufw.service(config('repcached_port'), 'close')
 
197
        os.remove(replication.REPCACHED_REPLICA_FILE)
 
198
        replica = None
 
199
 
103
200
    configs = {'mem_size': mem_size,
 
201
               'replica': replica,
104
202
               'large_pages_enabled': False}
105
203
 
 
204
    if replica:
 
205
        configs['repcached_port'] = config('repcached_port')
 
206
        ufw.service(config('repcached_port'), 'open')
 
207
 
106
208
    for key in ['request-limit', 'min-item-size', 'slab-page-size', 'threads',
107
209
                'disable-auto-cleanup', 'disable-cas', 'factor',
108
210
                'connection-limit', 'tcp-port', 'udp-port']: