~gnuoy/charms/trusty/percona-cluster/1454317

« back to all changes in this revision

Viewing changes to hooks/percona_utils.py

  • Committer: Liam Young
  • Date: 2015-09-30 08:06:12 UTC
  • mfrom: (60.2.16 percona-cluster)
  • Revision ID: liam.young@canonical.com-20150930080612-37dvdelm9iykj3as
Merged next in

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
import tempfile
6
6
import os
7
7
import shutil
 
8
import uuid
 
9
 
8
10
from charmhelpers.core.host import (
9
11
    lsb_release
10
12
)
20
22
    config,
21
23
    log,
22
24
    DEBUG,
 
25
    INFO,
 
26
    WARNING,
 
27
    ERROR,
23
28
)
24
29
from charmhelpers.fetch import (
25
30
    apt_install,
32
37
    MySQLHelper,
33
38
)
34
39
 
35
 
 
36
 
PACKAGES = [
37
 
    'percona-xtradb-cluster-server-5.5',
38
 
    'percona-xtradb-cluster-client-5.5',
39
 
]
 
40
# NOTE: python-mysqldb is installed by charmhelpers.contrib.database.mysql so
 
41
# hence why we import here
 
42
from MySQLdb import (
 
43
    OperationalError
 
44
)
40
45
 
41
46
KEY = "keys/repo.percona.com"
42
47
REPO = """deb http://repo.percona.com/apt {release} main
46
51
HOSTS_FILE = '/etc/hosts'
47
52
 
48
53
 
 
54
def determine_packages():
 
55
    if lsb_release()['DISTRIB_CODENAME'] > 'utopic':
 
56
        # NOTE(beisner): pxc 5.6 client package is not available
 
57
        # in Vivid, install mysql 5.6 client instead per
 
58
        # https://launchpad.net/bugs/1476845.
 
59
        return [
 
60
            'percona-xtradb-cluster-server-5.6',
 
61
            'mysql-client-5.6'
 
62
        ]
 
63
    else:
 
64
        return [
 
65
            'percona-xtradb-cluster-server-5.5',
 
66
            'percona-xtradb-cluster-client-5.5',
 
67
        ]
 
68
 
 
69
 
49
70
def seeded():
50
71
    ''' Check whether service unit is already seeded '''
51
72
    return os.path.exists(SEEDED_MARKER)
90
111
            return answers[0].address
91
112
 
92
113
 
 
114
def is_sufficient_peers():
 
115
    """If min-cluster-size has been provided, check that we have sufficient
 
116
    number of peers to proceed with bootstrapping percona cluster.
 
117
    """
 
118
    min_size = config('min-cluster-size')
 
119
    if min_size:
 
120
        size = 0
 
121
        for rid in relation_ids('cluster'):
 
122
            size = len(related_units(rid))
 
123
 
 
124
        # Include this unit
 
125
        size += 1
 
126
        if min_size > size:
 
127
            log("Insufficient number of units to configure percona cluster "
 
128
                "(expected=%s, got=%s)" % (min_size, size), level=INFO)
 
129
            return False
 
130
        else:
 
131
            log("Sufficient units available to configure percona cluster "
 
132
                "(>=%s)" % (min_size), level=DEBUG)
 
133
 
 
134
    return True
 
135
 
 
136
 
93
137
def get_cluster_hosts():
94
138
    hosts_map = {}
95
139
    hostname = get_host_ip()
247
291
            shutil.copy(src_file, dest_file)
248
292
        else:
249
293
            log("'%s' already exists, skipping" % dest_file, level='INFO')
 
294
 
 
295
 
 
296
def get_wsrep_value(key):
 
297
    m_helper = get_db_helper()
 
298
    try:
 
299
        m_helper.connect(password=m_helper.get_mysql_root_password())
 
300
    except OperationalError:
 
301
        log("Could not connect to db", DEBUG)
 
302
        return None
 
303
 
 
304
    cursor = m_helper.connection.cursor()
 
305
    ret = None
 
306
    try:
 
307
        cursor.execute("show status like '%s'" % (key))
 
308
        ret = cursor.fetchall()
 
309
    except:
 
310
        log("Failed to get '%s'", ERROR)
 
311
        return None
 
312
    finally:
 
313
        cursor.close()
 
314
 
 
315
    if ret:
 
316
        return ret[0][1]
 
317
 
 
318
    return None
 
319
 
 
320
 
 
321
def is_bootstrapped():
 
322
    if not is_sufficient_peers():
 
323
        return False
 
324
 
 
325
    uuids = []
 
326
    rids = relation_ids('cluster') or []
 
327
    for rid in rids:
 
328
        units = related_units(rid)
 
329
        units.append(local_unit())
 
330
        for unit in units:
 
331
            id = relation_get('bootstrap-uuid', unit=unit, rid=rid)
 
332
            if id:
 
333
                uuids.append(id)
 
334
 
 
335
    if uuids:
 
336
        if len(set(uuids)) > 1:
 
337
            log("Found inconsistent bootstrap uuids - %s" % (uuids), WARNING)
 
338
 
 
339
        return True
 
340
 
 
341
    return False
 
342
 
 
343
 
 
344
def notify_bootstrapped(cluster_rid=None, cluster_uuid=None):
 
345
    if cluster_rid:
 
346
        rids = [cluster_rid]
 
347
    else:
 
348
        rids = relation_ids('cluster')
 
349
        if not rids:
 
350
            log("No relation ids found for 'cluster'", level=INFO)
 
351
            return
 
352
 
 
353
    if not cluster_uuid:
 
354
        cluster_uuid = get_wsrep_value('wsrep_cluster_state_uuid')
 
355
        if not cluster_uuid:
 
356
            cluster_uuid = str(uuid.uuid4())
 
357
            log("Could not determine cluster uuid so using '%s' instead" %
 
358
                (cluster_uuid), INFO)
 
359
 
 
360
    log("Notifying peers that percona is bootstrapped (uuid=%s)" %
 
361
        (cluster_uuid), DEBUG)
 
362
    for rid in rids:
 
363
        relation_set(relation_id=rid, **{'bootstrap-uuid': cluster_uuid})