Lots of refactoring
This commit is contained in:
parent
159217d016
commit
30b31dc3f3
|
@ -42,3 +42,9 @@ options:
|
|||
type: int
|
||||
default: 5490
|
||||
description: Default multicast port number that will be used to communicate between HA Cluster nodes.
|
||||
root-password:
|
||||
type: string
|
||||
description: Root password for MySQL access; must be configured pre-deployment for Active-Active clusters.
|
||||
sst-password:
|
||||
type: string
|
||||
description: Re-sync account password for new cluster nodes; must be configured pre-deployment for Active-Active clusters.
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
''' Helper for working with a MySQL database '''
|
||||
# TODO: Contribute to charm-helpers
|
||||
import MySQLdb
|
||||
import socket
|
||||
import os
|
||||
from charmhelpers.core.host import pwgen, write_file, mkdir
|
||||
from charmhelpers.core.hookenv import unit_get, service_name
|
||||
from charmhelpers.fetch import apt_install, filter_installed_packages
|
||||
|
||||
from charmhelpers.core.host import pwgen
|
||||
from charmhelpers.core.hookenv import unit_get
|
||||
|
||||
try:
|
||||
import MySQLdb
|
||||
except ImportError:
|
||||
apt_install(filter_installed_packages(['python-mysqldb']),
|
||||
fatal=True)
|
||||
import MySQLdb
|
||||
|
||||
|
||||
class MySQLHelper():
|
||||
|
@ -39,7 +46,6 @@ class MySQLHelper():
|
|||
remote_ip))
|
||||
grants = [i[0] for i in cursor.fetchall()]
|
||||
except MySQLdb.OperationalError:
|
||||
print "No grants found"
|
||||
return False
|
||||
finally:
|
||||
cursor.close()
|
||||
|
@ -69,33 +75,38 @@ class MySQLHelper():
|
|||
finally:
|
||||
cursor.close()
|
||||
|
||||
_root_passwd = '/var/lib/mysql/mysql.passwd'
|
||||
_named_passwd = '/var/lib/mysql/mysql-{}.passwd'
|
||||
_root_passwd = '/var/lib/charm/{}/mysql.passwd'
|
||||
_named_passwd = '/var/lib/charm/{}/mysql-{}.passwd'
|
||||
|
||||
|
||||
def get_mysql_password(username=None):
|
||||
''' Retrieve or generate a mysql password for the provided username '''
|
||||
def get_mysql_password(username=None, password=None):
|
||||
''' Retrieve, generate or store a mysql password for
|
||||
the provided username '''
|
||||
if username:
|
||||
_passwd_file = _named_passwd.format(username)
|
||||
_passwd_file = _named_passwd.format(service_name(),
|
||||
username)
|
||||
else:
|
||||
_passwd_file = _root_passwd
|
||||
password = None
|
||||
_passwd_file = _root_passwd.format(service_name())
|
||||
_password = None
|
||||
if os.path.exists(_passwd_file):
|
||||
with open(_passwd_file, 'r') as passwd:
|
||||
password = passwd.read().strip()
|
||||
_password = passwd.read().strip()
|
||||
else:
|
||||
if not os.path.exists(os.path.dirname(_passwd_file)):
|
||||
os.makedirs(os.path.dirname(_passwd_file))
|
||||
password = pwgen(length=32)
|
||||
with open(_passwd_file, 'w') as passwd:
|
||||
passwd.write(password)
|
||||
os.chmod(_passwd_file, 0600)
|
||||
return password
|
||||
mkdir(os.path.dirname(_passwd_file),
|
||||
owner='root', group='root',
|
||||
perms=0770)
|
||||
# Force permissions - for some reason the chmod in makedirs fails
|
||||
os.chmod(os.path.dirname(_passwd_file), 0770)
|
||||
_password = password or pwgen(length=32)
|
||||
write_file(_passwd_file, _password,
|
||||
owner='root', group='root',
|
||||
perms=0660)
|
||||
return _password
|
||||
|
||||
|
||||
def get_mysql_root_password():
|
||||
def get_mysql_root_password(password=None):
|
||||
''' Retrieve or generate mysql root password for service units '''
|
||||
return get_mysql_password()
|
||||
return get_mysql_password(username=None, password=password)
|
||||
|
||||
|
||||
def configure_db(hostname,
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
#!/usr/bin/python
|
||||
# TODO: sync passwd files from seed to peers
|
||||
# TODO: Support relevant configuration options
|
||||
# TODO: Add db and db-admin hooks for mysql compat
|
||||
# TODO: Add README.md including squid-deb-proxy updates for repo.percona.com
|
||||
# TODO: Support changes to root and sstuser passwords
|
||||
|
||||
import sys
|
||||
import os
|
||||
import glob
|
||||
from charmhelpers.core.hookenv import (
|
||||
Hooks, UnregisteredHookError,
|
||||
log,
|
||||
|
@ -10,7 +14,8 @@ from charmhelpers.core.hookenv import (
|
|||
relation_set,
|
||||
relation_ids,
|
||||
unit_get,
|
||||
config
|
||||
config,
|
||||
service_name
|
||||
)
|
||||
from charmhelpers.core.host import (
|
||||
service_restart,
|
||||
|
@ -31,6 +36,7 @@ from percona_utils import (
|
|||
seeded, mark_seeded,
|
||||
configure_mysql_root_password
|
||||
)
|
||||
from mysql import get_mysql_password
|
||||
from charmhelpers.contrib.hahelpers.cluster import (
|
||||
peer_units,
|
||||
oldest_peer,
|
||||
|
@ -39,6 +45,10 @@ from charmhelpers.contrib.hahelpers.cluster import (
|
|||
is_leader
|
||||
)
|
||||
from mysql import configure_db
|
||||
from unison import (
|
||||
ssh_authorized_peers,
|
||||
sync_to_peers
|
||||
)
|
||||
|
||||
hooks = Hooks()
|
||||
|
||||
|
@ -46,11 +56,11 @@ hooks = Hooks()
|
|||
@hooks.hook('install')
|
||||
def install():
|
||||
setup_percona_repo()
|
||||
configure_mysql_root_password()
|
||||
render_config() # Render base configuation no cluster
|
||||
configure_mysql_root_password(config('root-password'))
|
||||
render_config() # Render base configuation (no cluster)
|
||||
apt_update(fatal=True)
|
||||
apt_install(PACKAGES, fatal=True)
|
||||
configure_sstuser()
|
||||
configure_sstuser(config('sst-password'))
|
||||
|
||||
|
||||
def render_config(clustered=False, hosts=[]):
|
||||
|
@ -61,15 +71,29 @@ def render_config(clustered=False, hosts=[]):
|
|||
{'cluster_name': 'juju_cluster',
|
||||
'private_address': get_host_ip(),
|
||||
'clustered': clustered,
|
||||
'cluster_hosts': ",".join(hosts)}
|
||||
)
|
||||
'cluster_hosts': ",".join(hosts),
|
||||
'sst_password': get_mysql_password(username='sstuser',
|
||||
password=config('sst-password'))
|
||||
})
|
||||
)
|
||||
# TODO: set 0640 and change group to mysql if avaliable
|
||||
os.chmod(MY_CNF, 0644)
|
||||
|
||||
|
||||
@hooks.hook('cluster-relation-joined')
|
||||
def cluster_relation_joined():
|
||||
ssh_authorized_peers(peer_interface='cluster',
|
||||
user='juju_ssh', group='root',
|
||||
ensure_local_user=True)
|
||||
|
||||
|
||||
@hooks.hook('cluster-relation-changed')
|
||||
@hooks.hook('upgrade-charm')
|
||||
@hooks.hook('config-changed')
|
||||
def cluster_changed():
|
||||
ssh_authorized_peers(peer_interface='cluster',
|
||||
user='juju_ssh', group='root',
|
||||
ensure_local_user=True)
|
||||
hosts = get_cluster_hosts()
|
||||
clustered = len(hosts) > 1
|
||||
pre_hash = file_hash(MY_CNF)
|
||||
|
@ -84,6 +108,11 @@ def cluster_changed():
|
|||
# Restart with new configuration
|
||||
service_restart('mysql')
|
||||
|
||||
if eligible_leader(LEADER_RES):
|
||||
files = glob.glob('/var/lib/charm/{}/*.passwd'.format(service_name()))
|
||||
sync_to_peers(peer_interface='cluster',
|
||||
user='juju_ssh', paths=files)
|
||||
|
||||
LEADER_RES = 'res_mysql_vip'
|
||||
|
||||
|
||||
|
@ -149,6 +178,10 @@ def shared_db_changed():
|
|||
relation_set(**return_data)
|
||||
relation_set(db_host=db_host)
|
||||
|
||||
files = glob.glob('/var/lib/charm/{}/*.passwd'.format(service_name()))
|
||||
sync_to_peers(peer_interface='cluster',
|
||||
user='juju_ssh', paths=files)
|
||||
|
||||
|
||||
@hooks.hook('ha-relation-joined')
|
||||
def ha_relation_joined():
|
||||
|
@ -162,18 +195,12 @@ def ha_relation_joined():
|
|||
log('Insufficient VIP information to configure cluster')
|
||||
sys.exit(1)
|
||||
|
||||
resources = {
|
||||
'res_mysql_vip': 'ocf:heartbeat:IPaddr2',
|
||||
}
|
||||
|
||||
resources = {'res_mysql_vip': 'ocf:heartbeat:IPaddr2'}
|
||||
resource_params = {
|
||||
'res_mysql_vip': 'params ip="%s" cidr_netmask="%s" nic="%s"' % \
|
||||
(vip, vip_cidr, vip_iface),
|
||||
}
|
||||
|
||||
groups = {
|
||||
'grp_percona_cluster': 'res_mysql_vip',
|
||||
}
|
||||
groups = {'grp_percona_cluster': 'res_mysql_vip'}
|
||||
|
||||
for rel_id in relation_ids('ha'):
|
||||
relation_set(rid=rel_id,
|
||||
|
|
|
@ -14,7 +14,7 @@ from charmhelpers.core.hookenv import (
|
|||
)
|
||||
from charmhelpers.fetch import (
|
||||
apt_install,
|
||||
filter_installed_packages
|
||||
filter_installed_packages,
|
||||
)
|
||||
from mysql import get_mysql_root_password
|
||||
|
||||
|
@ -35,7 +35,7 @@ except ImportError:
|
|||
PACKAGES = [
|
||||
'percona-xtradb-cluster-server-5.5',
|
||||
'percona-xtradb-cluster-client-5.5',
|
||||
'python-mysqldb'
|
||||
'unison'
|
||||
]
|
||||
|
||||
KEY = "keys/repo.percona.com"
|
||||
|
@ -72,6 +72,7 @@ def render_template(template_name, context, template_dir=TEMPLATES_DIR):
|
|||
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:
|
||||
|
@ -94,23 +95,26 @@ def get_cluster_hosts():
|
|||
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 's3cretPass';
|
||||
CREATE USER 'sstuser'@'localhost' IDENTIFIED BY '{}';
|
||||
GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'sstuser'@'localhost';
|
||||
EOF"""
|
||||
|
||||
|
||||
def configure_sstuser():
|
||||
subprocess.check_call(SQL_SST_USER_SETUP.format(get_mysql_root_password()),
|
||||
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():
|
||||
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()
|
||||
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" %
|
||||
|
|
|
@ -34,6 +34,6 @@ wsrep_sst_method=xtrabackup
|
|||
wsrep_cluster_name={{ cluster_name }}
|
||||
|
||||
# Authentication for SST method
|
||||
wsrep_sst_auth="sstuser:s3cretPass"
|
||||
wsrep_sst_auth="sstuser:{{ sst_password }}"
|
||||
|
||||
!includedir /etc/mysql/conf.d/
|
Loading…
Reference in New Issue