Support percona-cluster for ipv6.

This commit is contained in:
Hui Xiang 2014-08-03 23:26:23 +08:00
parent de3aa88b72
commit 0074d79575
5 changed files with 99 additions and 18 deletions

View File

@ -43,4 +43,8 @@ options:
The IP address and netmask of the 'access' network (e.g., 192.168.0.0/24)
.
This network will be used for access to database services.
prefer-ipv6:
default: false
type: boolean
description: "Enable IPv6."

View File

@ -10,7 +10,8 @@ from string import upper
from charmhelpers.core.host import pwgen, mkdir, write_file
from charmhelpers.core.hookenv import unit_get, service_name
from charmhelpers.core.hookenv import config as config_get
from charmhelpers.fetch import apt_install, filter_installed_packages
from charmhelpers.fetch import apt_install, apt_update, \
filter_installed_packages
from charmhelpers.contrib.peerstorage import (
peer_store,
@ -19,6 +20,7 @@ from charmhelpers.contrib.peerstorage import (
try:
import MySQLdb
except ImportError:
apt_update(fatal=True)
apt_install(filter_installed_packages(['python-mysqldb']),
fatal=True)
import MySQLdb
@ -179,7 +181,9 @@ def configure_db(hostname,
username,
admin=False):
''' Configure access to database for username from hostname '''
if hostname != unit_get('private-address'):
if config_get('prefer-ipv6'):
remote_ip = hostname
elif hostname != unit_get('private-address'):
remote_ip = socket.gethostbyname(hostname)
else:
remote_ip = '127.0.0.1'

View File

@ -3,6 +3,8 @@
import sys
import os
import socket
from charmhelpers.core.hookenv import (
Hooks, UnregisteredHookError,
log,
@ -27,7 +29,8 @@ from charmhelpers.fetch import (
add_source,
)
from charmhelpers.contrib.peerstorage import (
peer_echo
peer_echo,
peer_store,
)
from percona_utils import (
PACKAGES,
@ -57,6 +60,7 @@ from charmhelpers.payload.execd import execd_preinstall
from charmhelpers.contrib.network.ip import (
is_address_in_network,
get_address_in_network,
get_ipv6_addr,
)
hooks = Hooks()
@ -88,6 +92,11 @@ def render_config(clustered=False, hosts=[]):
'sst_password': get_mysql_password(username='sstuser',
password=config('sst-password'))
}
if config('prefer-ipv6'):
context['bind_address'] = '::'
context['wsrep_provider_options'] = 'gmcast.listen_addr=tcp://:::4567;'
context.update(parse_config())
write_file(path=MY_CNF,
content=render_template(os.path.basename(MY_CNF), context),
@ -118,7 +127,9 @@ def config_changed():
@hooks.hook('cluster-relation-changed')
def cluster_changed():
peer_echo()
if config('prefer-ipv6'):
peer_store('private-address', get_ipv6_addr())
peer_store('hostname', socket.gethostname())
config_changed()
@ -135,10 +146,16 @@ def db_changed(relation_id=None, unit=None, admin=None):
relation_clear(relation_id)
return
if is_clustered():
db_host = config('vip')
if config('prefer-ipv6'):
if is_clustered():
db_host = '[%s]' % config('vip')
else:
db_host = '[%s]' % get_ipv6_addr()
else:
db_host = unit_get('private-address')
if is_clustered():
db_host = config('vip')
else:
db_host = unit_get('private-address')
if admin not in [True, False]:
admin = relation_type() == 'db-admin'
@ -172,10 +189,16 @@ def shared_db_changed(relation_id=None, unit=None):
settings = relation_get(unit=unit,
rid=relation_id)
if is_clustered():
db_host = config('vip')
if config('prefer-ipv6'):
if is_clustered():
db_host = '[%s]' % config('vip')
else:
db_host = '[%s]' % get_ipv6_addr()
else:
db_host = unit_get('private-address')
if is_clustered():
db_host = config('vip')
else:
db_host = unit_get('private-address')
access_network = config('access-network')
@ -256,11 +279,17 @@ def ha_relation_joined():
log('Insufficient VIP information to configure cluster')
sys.exit(1)
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),
}
if config('prefer-ipv6'):
res_mysql_vip = 'ocf:heartbeat:IPv6addr'
vip_params = 'params ipv6addr="%s" cidr_netmask="%s" nic="%s"' % \
(vip, vip_cidr, vip_iface)
else:
res_mysql_vip = 'ocf:heartbeat:IPaddr2'
vip_params = 'params ip="%s" cidr_netmask="%s" nic="%s"' % \
(vip, vip_cidr, vip_iface)
resources = {'res_mysql_vip': res_mysql_vip}
resource_params = {'res_mysql_vip': vip_params}
groups = {'grp_percona_cluster': 'res_mysql_vip'}
for rel_id in relation_ids('ha'):

View File

@ -1,5 +1,4 @@
''' General utilities for percona '''
import subprocess
from subprocess import Popen, PIPE
import socket
import os
@ -13,11 +12,15 @@ from charmhelpers.core.hookenv import (
relation_get,
relation_set,
local_unit,
config,
)
from charmhelpers.fetch import (
apt_install,
filter_installed_packages,
)
from charmhelpers.contrib.network.ip import (
get_ipv6_addr,
)
from mysql import get_mysql_root_password, MySQLHelper
try:
@ -75,6 +78,14 @@ def render_template(template_name, context, template_dir=TEMPLATES_DIR):
# TODO: goto charm-helpers (I use this everywhere)
def get_host_ip(hostname=None):
if config('prefer-ipv6'):
private_address = get_ipv6_addr()
hostname = socket.gethostname()
host_map = {}
host_map[private_address] = hostname
render_hosts(host_map)
return hostname
hostname = hostname or unit_get('private-address')
try:
# Test to see if already an IPv4 address
@ -90,10 +101,20 @@ def get_host_ip(hostname=None):
def get_cluster_hosts():
hosts = [get_host_ip()]
hosts_map = {}
for relid in relation_ids('cluster'):
for unit in related_units(relid):
hosts.append(get_host_ip(relation_get('private-address',
unit, relid)))
private_address = relation_get('private-address', unit, relid)
if config('prefer-ipv6'):
hostname = relation_get('hostname', unit, relid)
if not hostname or hostname in hosts:
continue
hosts_map[private_address] = hostname
hosts.append(hostname)
else:
hosts.append(get_host_ip(private_address))
render_hosts(hosts_map)
return hosts
SQL_SST_USER_SETUP = "GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.*" \
@ -133,3 +154,18 @@ def relation_clear(r_id=None):
settings[setting] = None
relation_set(relation_id=r_id,
**settings)
def render_hosts(map):
if len(map) == 0:
return
with open('/etc/hosts', 'a+r') as hosts:
for ip, hostname in map.items():
if not ip or not hostname:
continue
for line in hosts:
if line.startswith(ip):
break
else:
hosts.write(ip + ' ' + hostname + '\n')

View File

@ -1,6 +1,14 @@
# Juju managed file - don't change as charm will overwrite your changed!
[mysqld]
{% if bind_address %}
bind-address = {{ bind_address }}
{% endif %}
{% if wsrep_provider_options %}
wsrep_provider_options = {{ wsrep_provider_options }}
{% endif %}
datadir=/var/lib/mysql
user=mysql