129 lines
3.6 KiB
Python
129 lines
3.6 KiB
Python
import os
|
|
import re
|
|
from subprocess import check_output
|
|
|
|
from charms.reactive import set_flag, when, when_not, hook
|
|
from charms.reactive.flags import clear_flag
|
|
|
|
|
|
from charmhelpers.core.templating import render
|
|
from charmhelpers.fetch import apt_update, apt_install
|
|
from charmhelpers.core.hookenv import config, is_leader
|
|
from charmhelpers.core.host import service_restart
|
|
from charmhelpers.core.host import service_pause, service_resume
|
|
|
|
from charms.layer import status
|
|
|
|
|
|
SYSCTL_FILE = os.path.join(os.sep, "etc", "sysctl.d", "50-keepalived.conf")
|
|
KEEPALIVED_CONFIG_FILE = os.path.join(os.sep, "etc", "keepalived", "keepalived.conf")
|
|
|
|
|
|
@when_not("keepalived.package.installed")
|
|
def install_keepalived_package():
|
|
"""Install keepalived package"""
|
|
status.maintenance("Installing keepalived")
|
|
|
|
apt_update(fatal=True)
|
|
apt_install(["keepalived", "net-tools"], fatal=True)
|
|
|
|
set_flag("keepalived.package.installed")
|
|
|
|
|
|
def default_route_interface():
|
|
"""Returns the network interface of the system's default route"""
|
|
cmd = ["route"]
|
|
output = check_output(cmd).decode("utf8")
|
|
for line in output.split("\n"):
|
|
if "default" in line:
|
|
default_interface = line.split(" ")[-1]
|
|
return default_interface
|
|
|
|
|
|
@when("keepalived.package.installed")
|
|
@when_not("keepalived.started")
|
|
@when_not("upgrade.series.in-progress")
|
|
def configure_keepalived_service():
|
|
"""Set up the keepalived service"""
|
|
|
|
virtual_ip = config().get("virtual_ip")
|
|
if virtual_ip == "":
|
|
status.blocked("Please configure virtual ips")
|
|
return
|
|
|
|
network_interface = config().get("network_interface")
|
|
if network_interface == "":
|
|
network_interface = default_route_interface()
|
|
|
|
context = {
|
|
"is_leader": is_leader(),
|
|
"virtual_ip": virtual_ip,
|
|
"network_interface": network_interface,
|
|
"router_id": config().get("router_id"),
|
|
"service_port": config().get("port"),
|
|
"healthcheck_interval": config().get("healthcheck_interval"),
|
|
}
|
|
render(
|
|
source="keepalived.conf",
|
|
target=KEEPALIVED_CONFIG_FILE,
|
|
context=context,
|
|
perms=0o644,
|
|
)
|
|
service_restart("keepalived")
|
|
|
|
render(
|
|
source="50-keepalived.conf",
|
|
target=SYSCTL_FILE,
|
|
context={"sysctl": {"net.ipv4.ip_nonlocal_bind": 1}},
|
|
perms=0o644,
|
|
)
|
|
service_restart("procps")
|
|
|
|
status.active("VIP ready")
|
|
set_flag("keepalived.started")
|
|
|
|
|
|
@when("config.changed")
|
|
def reconfigure():
|
|
clear_flag("keepalived.started")
|
|
|
|
|
|
@when("website.available", "keepalived.started")
|
|
def website_available(website):
|
|
ipaddr = re.split("/", config()["virtual_ip"])[0]
|
|
vip_hostname = config()["vip_hostname"]
|
|
hostname = vip_hostname if vip_hostname else ipaddr
|
|
# a port to export over a relation
|
|
# TODO: this could be more tightly coupled with the actual
|
|
# service via a relation
|
|
port = config()["port"]
|
|
website.configure(port=port, private_address=ipaddr, hostname=hostname)
|
|
|
|
|
|
@when("loadbalancer.available", "keepalived.started")
|
|
def loadbalancer_available(loadbalancer):
|
|
"""Send the virtual IP"""
|
|
ipaddr = re.split("/", config()["virtual_ip"])[0]
|
|
port = config()["port"]
|
|
loadbalancer.set_address_port(ipaddr, port)
|
|
|
|
|
|
@hook("upgrade-charm")
|
|
def upgrade_charm():
|
|
clear_flag("keepalived.started")
|
|
|
|
|
|
@hook("pre-series-upgrade")
|
|
def pre_series_upgrade():
|
|
service_pause("keepalived")
|
|
service_pause("procps")
|
|
status.blocked("Series upgrade in progress")
|
|
|
|
|
|
@hook("post-series-upgrade")
|
|
def post_series_upgrade():
|
|
service_resume("keepalived")
|
|
service_resume("procps")
|
|
clear_flag("keepalived.package.installed")
|
|
clear_flag("keepalived.started")
|