''' General utilities for percona ''' import subprocess from subprocess import Popen, PIPE import socket import os from charmhelpers.core.host import ( lsb_release, ) from charmhelpers.core.hookenv import ( unit_get, relation_ids, related_units, relation_get, relation_set, local_unit, ) from charmhelpers.fetch import ( apt_install, filter_installed_packages, ) from mysql import get_mysql_root_password try: import jinja2 except ImportError: apt_install(filter_installed_packages(['python-jinja2']), fatal=True) import jinja2 try: import dns.resolver except ImportError: apt_install(filter_installed_packages(['python-dnspython']), fatal=True) import dns.resolver PACKAGES = [ 'percona-xtradb-cluster-server-5.5', 'percona-xtradb-cluster-client-5.5', 'unison' ] KEY = "keys/repo.percona.com" REPO = """deb http://repo.percona.com/apt {release} main deb-src http://repo.percona.com/apt {release} main""" MY_CNF = "/etc/mysql/my.cnf" SEEDED_MARKER = "/var/lib/mysql/seeded" def seeded(): ''' Check whether service unit is already seeded ''' return os.path.exists(SEEDED_MARKER) def mark_seeded(): ''' Mark service unit as seeded ''' with open(SEEDED_MARKER, 'w') as seeded: seeded.write('done') def setup_percona_repo(): ''' Configure service unit to use percona repositories ''' with open('/etc/apt/sources.list.d/percona.list', 'w') as sources: sources.write(REPO.format(release=lsb_release()['DISTRIB_CODENAME'])) subprocess.check_call(['apt-key', 'add', KEY]) TEMPLATES_DIR = 'templates' def render_template(template_name, context, template_dir=TEMPLATES_DIR): templates = jinja2.Environment( loader=jinja2.FileSystemLoader(template_dir)) template = templates.get_template(template_name) return template.render(context) # TODO: goto charm-helpers (I use this everywhere) def get_host_ip(hostname=None): hostname = hostname or unit_get('private-address') try: # Test to see if already an IPv4 address socket.inet_aton(hostname) return hostname except socket.error: # This may throw an NXDOMAIN exception; in which case # things are badly broken so just let it kill the hook answers = dns.resolver.query(hostname, 'A') if answers: return answers[0].address def get_cluster_hosts(): hosts = [get_host_ip()] for relid in relation_ids('cluster'): for unit in related_units(relid): hosts.append(get_host_ip(relation_get('private-address', unit, relid))) return hosts # TODO: refactor to use mysql helper when it support setting arbitary # permissions SQL_SST_USER_SETUP = """mysql --user=root --password={} << EOF CREATE USER 'sstuser'@'localhost' IDENTIFIED BY '{}'; GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'sstuser'@'localhost'; EOF""" def configure_sstuser(sst_password): subprocess.check_call(SQL_SST_USER_SETUP.format(get_mysql_root_password(), sst_password), shell=True) # TODO: mysql charmhelper def configure_mysql_root_password(password): ''' Configure debconf with root password ''' dconf = Popen(['debconf-set-selections'], stdin=PIPE) package = "percona-server-server" root_pass = get_mysql_root_password(password) dconf.stdin.write("%s %s/root_password password %s\n" % (package, package, root_pass)) dconf.stdin.write("%s %s/root_password_again password %s\n" % (package, package, root_pass)) dconf.communicate() dconf.wait() # TODO: Submit for charmhelper def relation_clear(r_id=None): ''' Clears any relation data already set on relation r_id ''' settings = relation_get(rid=r_id, unit=local_unit()) for setting in settings: if setting not in ['public-address', 'private-address']: settings[setting] = None relation_set(relation_id=r_id, **settings)