538 lines
17 KiB
Python
Raw Normal View History

from charmhelpers.core.host import (
service_running,
service_stop,
2014-09-19 10:18:01 +01:00
service_restart,
lsb_release
)
from charmhelpers.core.hookenv import (
log,
config,
2013-11-19 13:52:35 +00:00
relations_of_type,
2014-06-06 11:11:53 +00:00
unit_private_ip,
is_relation_made,
)
2013-09-02 17:14:27 +01:00
from charmhelpers.fetch import (
2014-03-06 12:39:50 +00:00
apt_upgrade,
apt_update,
apt_install,
)
from charmhelpers.contrib.network.ovs import (
add_bridge,
add_bridge_port,
full_restart
)
from charmhelpers.contrib.openstack.utils import (
configure_installation_source,
get_os_codename_install_source,
get_os_codename_package,
get_hostname
)
from charmhelpers.contrib.openstack.neutron import (
determine_dkms_package
)
import charmhelpers.contrib.openstack.context as context
from charmhelpers.contrib.openstack.context import (
SyslogContext
)
import charmhelpers.contrib.openstack.templating as templating
from charmhelpers.contrib.openstack.neutron import headers_package
2013-07-22 16:39:07 +01:00
from quantum_contexts import (
CORE_PLUGIN, OVS, NVP, NSX,
2013-09-04 11:03:20 +01:00
NEUTRON, QUANTUM,
networking_name,
2013-07-22 16:39:07 +01:00
QuantumGatewayContext,
NetworkServiceContext,
L3AgentContext,
2013-07-22 16:39:07 +01:00
ExternalPortContext,
remap_plugin
2013-07-22 16:39:07 +01:00
)
2013-09-04 10:46:54 +01:00
from copy import deepcopy
def valid_plugin():
2013-09-04 10:46:54 +01:00
return config('plugin') in CORE_PLUGIN[networking_name()]
QUANTUM_CONF_DIR = '/etc/quantum'
2013-09-04 10:46:54 +01:00
QUANTUM_OVS_PLUGIN_CONF = \
2012-10-26 17:56:42 +02:00
"/etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini"
2013-09-04 10:46:54 +01:00
QUANTUM_NVP_PLUGIN_CONF = \
2013-06-26 17:02:28 +01:00
"/etc/quantum/plugins/nicira/nvp.ini"
2013-09-04 10:46:54 +01:00
QUANTUM_PLUGIN_CONF = {
OVS: QUANTUM_OVS_PLUGIN_CONF,
NVP: QUANTUM_NVP_PLUGIN_CONF
}
2012-10-26 17:56:42 +02:00
NEUTRON_CONF_DIR = '/etc/neutron'
2013-09-04 10:46:54 +01:00
NEUTRON_OVS_PLUGIN_CONF = \
"/etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini"
2013-12-18 09:50:58 +00:00
NEUTRON_ML2_PLUGIN_CONF = \
"/etc/neutron/plugins/ml2/ml2_conf.ini"
2013-09-04 10:46:54 +01:00
NEUTRON_NVP_PLUGIN_CONF = \
"/etc/neutron/plugins/nicira/nvp.ini"
NEUTRON_NSX_PLUGIN_CONF = \
"/etc/neutron/plugins/vmware/nsx.ini"
2013-09-04 10:46:54 +01:00
NEUTRON_PLUGIN_CONF = {
OVS: NEUTRON_OVS_PLUGIN_CONF,
NVP: NEUTRON_NVP_PLUGIN_CONF,
NSX: NEUTRON_NSX_PLUGIN_CONF,
2013-09-04 10:46:54 +01:00
}
QUANTUM_GATEWAY_PKGS = {
OVS: [
"quantum-plugin-openvswitch-agent",
"quantum-l3-agent",
"quantum-dhcp-agent",
2013-01-18 08:51:11 +00:00
'python-mysqldb',
2014-03-28 12:02:09 +01:00
'python-psycopg2',
2013-01-18 08:51:11 +00:00
"nova-api-metadata"
],
2013-06-26 17:02:28 +01:00
NVP: [
2013-06-27 22:20:07 +01:00
"openvswitch-switch",
2013-01-18 08:51:11 +00:00
"quantum-dhcp-agent",
2013-06-26 17:02:28 +01:00
'python-mysqldb',
2014-03-28 12:02:09 +01:00
'python-psycopg2',
2013-01-18 08:51:11 +00:00
"nova-api-metadata"
]
}
2013-01-18 08:51:11 +00:00
2013-09-04 10:46:54 +01:00
NEUTRON_GATEWAY_PKGS = {
OVS: [
"neutron-plugin-openvswitch-agent",
"openvswitch-switch",
2013-09-04 10:46:54 +01:00
"neutron-l3-agent",
"neutron-dhcp-agent",
'python-mysqldb',
2014-03-28 12:02:09 +01:00
'python-psycopg2',
2013-09-04 12:35:45 +01:00
'python-oslo.config', # Force upgrade
"nova-api-metadata",
2014-03-27 22:35:15 +00:00
"neutron-plugin-metering-agent",
"neutron-lbaas-agent",
2013-09-04 10:46:54 +01:00
],
NVP: [
"neutron-dhcp-agent",
'python-mysqldb',
2014-03-28 12:02:09 +01:00
'python-psycopg2',
2013-09-04 12:35:45 +01:00
'python-oslo.config', # Force upgrade
2013-09-04 10:46:54 +01:00
"nova-api-metadata"
]
}
NEUTRON_GATEWAY_PKGS[NSX] = NEUTRON_GATEWAY_PKGS[NVP]
2012-10-26 17:56:42 +02:00
2013-09-04 10:46:54 +01:00
GATEWAY_PKGS = {
QUANTUM: QUANTUM_GATEWAY_PKGS,
NEUTRON: NEUTRON_GATEWAY_PKGS,
}
2012-10-26 17:56:42 +02:00
def get_early_packages():
'''Return a list of package for pre-install based on configured plugin'''
if config('plugin') in [OVS]:
pkgs = determine_dkms_package()
2013-03-20 16:08:54 +00:00
else:
return []
2012-12-03 15:16:55 +00:00
# ensure headers are installed build any required dkms packages
if [p for p in pkgs if 'dkms' in p]:
return pkgs + [headers_package()]
return pkgs
2012-10-26 17:56:42 +02:00
def get_packages():
'''Return a list of packages for install based on the configured plugin'''
plugin = remap_plugin(config('plugin'))
packages = deepcopy(GATEWAY_PKGS[networking_name()][plugin])
if (get_os_codename_install_source(config('openstack-origin'))
2014-09-19 10:18:01 +01:00
>= 'icehouse' and plugin == 'ovs'
and lsb_release()['DISTRIB_CODENAME'] < 'utopic'):
# NOTE(jamespage) neutron-vpn-agent supercedes l3-agent for icehouse
2014-09-19 10:18:01 +01:00
# but openswan was removed in utopic.
packages.remove('neutron-l3-agent')
packages.append('neutron-vpn-agent')
2014-09-19 10:18:01 +01:00
packages.append('openswan')
return packages
2012-10-26 17:56:42 +02:00
def get_common_package():
if get_os_codename_package('quantum-common', fatal=False) is not None:
return 'quantum-common'
else:
return 'neutron-common'
2012-10-26 17:56:42 +02:00
EXT_PORT_CONF = '/etc/init/ext-port.conf'
TEMPLATES = 'templates'
2012-10-26 17:56:42 +02:00
QUANTUM_CONF = "/etc/quantum/quantum.conf"
2013-09-04 10:46:54 +01:00
QUANTUM_L3_AGENT_CONF = "/etc/quantum/l3_agent.ini"
QUANTUM_DHCP_AGENT_CONF = "/etc/quantum/dhcp_agent.ini"
QUANTUM_METADATA_AGENT_CONF = "/etc/quantum/metadata_agent.ini"
2012-10-26 17:56:42 +02:00
2013-09-04 10:46:54 +01:00
NEUTRON_CONF = "/etc/neutron/neutron.conf"
NEUTRON_L3_AGENT_CONF = "/etc/neutron/l3_agent.ini"
NEUTRON_DHCP_AGENT_CONF = "/etc/neutron/dhcp_agent.ini"
NEUTRON_DNSMASQ_CONF = "/etc/neutron/dnsmasq.conf"
2013-09-04 10:46:54 +01:00
NEUTRON_METADATA_AGENT_CONF = "/etc/neutron/metadata_agent.ini"
NEUTRON_METERING_AGENT_CONF = "/etc/neutron/metering_agent.ini"
2014-03-27 22:35:15 +00:00
NEUTRON_LBAAS_AGENT_CONF = "/etc/neutron/lbaas_agent.ini"
2014-03-27 22:45:27 +00:00
NEUTRON_VPNAAS_AGENT_CONF = "/etc/neutron/vpn_agent.ini"
2014-03-27 23:03:43 +00:00
NEUTRON_FWAAS_CONF = "/etc/neutron/fwaas_driver.ini"
NOVA_CONF_DIR = '/etc/nova'
2013-01-18 08:51:11 +00:00
NOVA_CONF = "/etc/nova/nova.conf"
2013-09-04 10:46:54 +01:00
NOVA_CONFIG_FILES = {
NOVA_CONF: {
'hook_contexts': [context.SharedDBContext(ssl_dir=NOVA_CONF_DIR),
2014-03-28 12:02:09 +01:00
context.PostgresqlDBContext(),
2013-07-22 16:39:07 +01:00
NetworkServiceContext(),
QuantumGatewayContext(),
SyslogContext()],
'services': ['nova-api-metadata']
},
}
2013-04-12 15:56:50 +01:00
2013-09-04 10:46:54 +01:00
QUANTUM_SHARED_CONFIG_FILES = {
QUANTUM_DHCP_AGENT_CONF: {
'hook_contexts': [QuantumGatewayContext()],
'services': ['quantum-dhcp-agent']
},
QUANTUM_METADATA_AGENT_CONF: {
'hook_contexts': [NetworkServiceContext(),
QuantumGatewayContext()],
2013-09-04 10:46:54 +01:00
'services': ['quantum-metadata-agent']
},
}
QUANTUM_SHARED_CONFIG_FILES.update(NOVA_CONFIG_FILES)
NEUTRON_SHARED_CONFIG_FILES = {
NEUTRON_DHCP_AGENT_CONF: {
'hook_contexts': [QuantumGatewayContext()],
'services': ['neutron-dhcp-agent']
},
NEUTRON_DNSMASQ_CONF: {
'hook_contexts': [QuantumGatewayContext()],
'services': ['neutron-dhcp-agent']
},
2013-09-04 10:46:54 +01:00
NEUTRON_METADATA_AGENT_CONF: {
'hook_contexts': [NetworkServiceContext(),
QuantumGatewayContext()],
2013-09-04 10:46:54 +01:00
'services': ['neutron-metadata-agent']
},
}
NEUTRON_SHARED_CONFIG_FILES.update(NOVA_CONFIG_FILES)
QUANTUM_OVS_CONFIG_FILES = {
QUANTUM_CONF: {
'hook_contexts': [context.AMQPContext(ssl_dir=QUANTUM_CONF_DIR),
QuantumGatewayContext(),
SyslogContext()],
'services': ['quantum-l3-agent',
'quantum-dhcp-agent',
'quantum-metadata-agent',
'quantum-plugin-openvswitch-agent']
},
2013-09-04 10:46:54 +01:00
QUANTUM_L3_AGENT_CONF: {
'hook_contexts': [NetworkServiceContext(),
QuantumGatewayContext()],
'services': ['quantum-l3-agent']
},
2013-09-04 10:46:54 +01:00
QUANTUM_OVS_PLUGIN_CONF: {
'hook_contexts': [QuantumGatewayContext()],
'services': ['quantum-plugin-openvswitch-agent']
},
EXT_PORT_CONF: {
2013-07-22 16:39:07 +01:00
'hook_contexts': [ExternalPortContext()],
'services': []
}
}
2013-09-04 10:46:54 +01:00
QUANTUM_OVS_CONFIG_FILES.update(QUANTUM_SHARED_CONFIG_FILES)
NEUTRON_OVS_CONFIG_FILES = {
NEUTRON_CONF: {
'hook_contexts': [context.AMQPContext(ssl_dir=NEUTRON_CONF_DIR),
QuantumGatewayContext(),
SyslogContext()],
2013-09-04 10:46:54 +01:00
'services': ['neutron-l3-agent',
'neutron-dhcp-agent',
'neutron-metadata-agent',
'neutron-plugin-openvswitch-agent',
2014-03-29 20:29:38 +00:00
'neutron-plugin-metering-agent',
2014-03-27 22:35:15 +00:00
'neutron-metering-agent',
'neutron-lbaas-agent',
'neutron-plugin-vpn-agent',
'neutron-vpn-agent']
2013-09-04 10:46:54 +01:00
},
NEUTRON_L3_AGENT_CONF: {
'hook_contexts': [NetworkServiceContext(),
L3AgentContext(),
QuantumGatewayContext()],
2013-09-04 10:46:54 +01:00
'services': ['neutron-l3-agent']
},
NEUTRON_METERING_AGENT_CONF: {
'hook_contexts': [QuantumGatewayContext()],
2014-03-27 22:52:56 +00:00
'services': ['neutron-plugin-metering-agent',
'neutron-metering-agent']
},
2014-03-27 22:35:15 +00:00
NEUTRON_LBAAS_AGENT_CONF: {
'hook_contexts': [QuantumGatewayContext()],
'services': ['neutron-lbaas-agent']
},
NEUTRON_VPNAAS_AGENT_CONF: {
'hook_contexts': [QuantumGatewayContext()],
'services': ['neutron-plugin-vpn-agent',
'neutron-vpn-agent']
},
2014-03-27 23:03:43 +00:00
NEUTRON_FWAAS_CONF: {
'hook_contexts': [QuantumGatewayContext()],
'services': ['neutron-l3-agent']
},
2013-09-04 10:46:54 +01:00
NEUTRON_OVS_PLUGIN_CONF: {
'hook_contexts': [QuantumGatewayContext()],
2013-09-04 10:46:54 +01:00
'services': ['neutron-plugin-openvswitch-agent']
},
2013-12-18 09:50:58 +00:00
NEUTRON_ML2_PLUGIN_CONF: {
'hook_contexts': [QuantumGatewayContext()],
'services': ['neutron-plugin-openvswitch-agent']
},
2013-09-04 10:46:54 +01:00
EXT_PORT_CONF: {
'hook_contexts': [ExternalPortContext()],
'services': []
}
}
NEUTRON_OVS_CONFIG_FILES.update(NEUTRON_SHARED_CONFIG_FILES)
2013-07-01 17:35:04 +01:00
2013-09-04 10:46:54 +01:00
QUANTUM_NVP_CONFIG_FILES = {
QUANTUM_CONF: {
2014-05-04 12:30:50 -05:00
'hook_contexts': [context.AMQPContext(ssl_dir=QUANTUM_CONF_DIR),
QuantumGatewayContext(),
SyslogContext()],
'services': ['quantum-dhcp-agent', 'quantum-metadata-agent']
},
}
2013-09-04 10:46:54 +01:00
QUANTUM_NVP_CONFIG_FILES.update(QUANTUM_SHARED_CONFIG_FILES)
NEUTRON_NVP_CONFIG_FILES = {
NEUTRON_CONF: {
2014-05-04 12:30:50 -05:00
'hook_contexts': [context.AMQPContext(ssl_dir=NEUTRON_CONF_DIR),
QuantumGatewayContext(),
SyslogContext()],
2013-09-04 10:46:54 +01:00
'services': ['neutron-dhcp-agent', 'neutron-metadata-agent']
},
}
NEUTRON_NVP_CONFIG_FILES.update(NEUTRON_SHARED_CONFIG_FILES)
2013-07-01 17:35:04 +01:00
CONFIG_FILES = {
2013-09-04 10:46:54 +01:00
QUANTUM: {
NVP: QUANTUM_NVP_CONFIG_FILES,
OVS: QUANTUM_OVS_CONFIG_FILES,
},
NEUTRON: {
NSX: NEUTRON_NVP_CONFIG_FILES,
2013-09-04 10:46:54 +01:00
NVP: NEUTRON_NVP_CONFIG_FILES,
OVS: NEUTRON_OVS_CONFIG_FILES,
},
}
2013-07-01 17:35:04 +01:00
def register_configs():
''' Register config files with their respective contexts. '''
2013-09-04 10:46:54 +01:00
release = get_os_codename_install_source(config('openstack-origin'))
configs = templating.OSConfigRenderer(templates_dir=TEMPLATES,
openstack_release=release)
plugin = remap_plugin(config('plugin'))
2013-09-04 10:46:54 +01:00
name = networking_name()
2013-12-18 09:50:58 +00:00
if plugin == 'ovs':
2013-12-18 09:57:34 +00:00
# NOTE: deal with switch to ML2 plugin for >= icehouse
2013-12-18 09:50:58 +00:00
drop_config = NEUTRON_ML2_PLUGIN_CONF
if release >= 'icehouse':
drop_config = NEUTRON_OVS_PLUGIN_CONF
if drop_config in CONFIG_FILES[name][plugin]:
CONFIG_FILES[name][plugin].pop(drop_config)
if is_relation_made('amqp-nova'):
amqp_nova_ctxt = context.AMQPContext(
ssl_dir=NOVA_CONF_DIR,
rel_name='amqp-nova',
relation_prefix='nova')
else:
amqp_nova_ctxt = context.AMQPContext(
ssl_dir=NOVA_CONF_DIR,
rel_name='amqp')
CONFIG_FILES[name][plugin][NOVA_CONF][
'hook_contexts'].append(amqp_nova_ctxt)
2013-09-04 10:46:54 +01:00
for conf in CONFIG_FILES[name][plugin]:
configs.register(conf,
CONFIG_FILES[name][plugin][conf]['hook_contexts'])
return configs
def stop_services():
name = networking_name()
svcs = set()
for ctxt in CONFIG_FILES[name][config('plugin')].itervalues():
for svc in ctxt['services']:
svcs.add(svc)
for svc in svcs:
service_stop(svc)
def restart_map():
'''
Determine the correct resource map to be passed to
charmhelpers.core.restart_on_change() based on the services configured.
:returns: dict: A dictionary mapping config file to lists of services
that should be restarted when file changes.
'''
2013-09-04 10:46:54 +01:00
_map = {}
2013-12-18 09:50:58 +00:00
plugin = config('plugin')
2013-09-04 10:46:54 +01:00
name = networking_name()
2013-12-18 09:50:58 +00:00
for f, ctxt in CONFIG_FILES[name][plugin].iteritems():
svcs = []
for svc in ctxt['services']:
svcs.append(svc)
if svcs:
2013-09-04 10:46:54 +01:00
_map[f] = svcs
return _map
2013-01-18 08:51:11 +00:00
2012-12-03 15:16:55 +00:00
INT_BRIDGE = "br-int"
EXT_BRIDGE = "br-ex"
2013-03-20 16:08:54 +00:00
DHCP_AGENT = "DHCP Agent"
L3_AGENT = "L3 Agent"
2013-09-04 10:46:54 +01:00
# TODO: make work with neutron
def reassign_agent_resources():
2013-03-20 16:08:54 +00:00
''' Use agent scheduler API to detect down agents and re-schedule '''
2013-07-22 16:39:07 +01:00
env = NetworkServiceContext()()
if not env:
log('Unable to re-assign resources at this time')
return
try:
from quantumclient.v2_0 import client
except ImportError:
''' Try to import neutronclient instead for havana+ '''
from neutronclient.v2_0 import client
auth_url = '%(auth_protocol)s://%(keystone_host)s:%(auth_port)s/v2.0' % env
2013-03-20 16:08:54 +00:00
quantum = client.Client(username=env['service_username'],
password=env['service_password'],
tenant_name=env['service_tenant'],
auth_url=auth_url,
region_name=env['region'])
2013-11-19 14:37:17 +00:00
partner_gateways = [unit_private_ip().split('.')[0]]
for partner_gateway in relations_of_type(reltype='cluster'):
gateway_hostname = get_hostname(partner_gateway['private-address'])
partner_gateways.append(gateway_hostname.partition('.')[0])
2013-03-20 16:08:54 +00:00
agents = quantum.list_agents(agent_type=DHCP_AGENT)
dhcp_agents = []
l3_agents = []
2013-03-20 16:08:54 +00:00
networks = {}
for agent in agents['agents']:
if not agent['alive']:
log('DHCP Agent %s down' % agent['id'])
2013-03-20 16:08:54 +00:00
for network in \
quantum.list_networks_on_dhcp_agent(
agent['id'])['networks']:
2013-03-20 16:08:54 +00:00
networks[network['id']] = agent['id']
else:
if agent['host'].partition('.')[0] in partner_gateways:
2013-11-19 14:37:17 +00:00
dhcp_agents.append(agent['id'])
2013-03-20 16:08:54 +00:00
agents = quantum.list_agents(agent_type=L3_AGENT)
routers = {}
for agent in agents['agents']:
if not agent['alive']:
log('L3 Agent %s down' % agent['id'])
2013-03-20 16:08:54 +00:00
for router in \
quantum.list_routers_on_l3_agent(
agent['id'])['routers']:
2013-03-20 16:08:54 +00:00
routers[router['id']] = agent['id']
else:
if agent['host'].split('.')[0] in partner_gateways:
2013-11-19 14:37:17 +00:00
l3_agents.append(agent['id'])
2013-03-20 16:08:54 +00:00
if len(dhcp_agents) == 0 or len(l3_agents) == 0:
log('Unable to relocate resources, there are %s dhcp_agents and %s \
l3_agents in this cluster' % (len(dhcp_agents), len(l3_agents)))
return
2013-03-20 16:08:54 +00:00
index = 0
2013-03-20 16:08:54 +00:00
for router_id in routers:
agent = index % len(l3_agents)
log('Moving router %s from %s to %s' %
(router_id, routers[router_id], l3_agents[agent]))
2013-03-20 16:08:54 +00:00
quantum.remove_router_from_l3_agent(l3_agent=routers[router_id],
router_id=router_id)
quantum.add_router_to_l3_agent(l3_agent=l3_agents[agent],
2013-03-20 16:08:54 +00:00
body={'router_id': router_id})
index += 1
2013-03-20 16:08:54 +00:00
index = 0
2013-03-20 16:08:54 +00:00
for network_id in networks:
agent = index % len(dhcp_agents)
log('Moving network %s from %s to %s' %
(network_id, networks[network_id], dhcp_agents[agent]))
2013-03-20 16:08:54 +00:00
quantum.remove_network_from_dhcp_agent(dhcp_agent=networks[network_id],
network_id=network_id)
quantum.add_network_to_dhcp_agent(dhcp_agent=dhcp_agents[agent],
2013-03-20 16:08:54 +00:00
body={'network_id': network_id})
index += 1
def services():
''' Returns a list of services associate with this charm '''
_services = []
for v in restart_map().values():
_services = _services + v
return list(set(_services))
2014-04-01 13:17:44 +01:00
def do_openstack_upgrade():
"""
Perform an upgrade. Takes care of upgrading packages, rewriting
configs, database migrations and potentially any other post-upgrade
actions.
"""
new_src = config('openstack-origin')
new_os_rel = get_os_codename_install_source(new_src)
log('Performing OpenStack upgrade to %s.' % (new_os_rel))
configure_installation_source(new_src)
dpkg_opts = [
'--option', 'Dpkg::Options::=--force-confnew',
'--option', 'Dpkg::Options::=--force-confdef',
]
apt_update(fatal=True)
2014-03-06 12:39:50 +00:00
apt_upgrade(options=dpkg_opts,
2014-03-06 13:43:16 +00:00
fatal=True, dist=True)
apt_install(get_early_packages(), fatal=True)
apt_install(get_packages(), fatal=True)
# set CONFIGS to load templates from new release
2014-04-01 13:17:44 +01:00
configs = register_configs()
configs.write_all()
[service_restart(s) for s in services()]
2014-04-01 13:17:44 +01:00
return configs
def configure_ovs():
if config('plugin') == OVS:
2013-10-22 15:01:55 -07:00
if not service_running('openvswitch-switch'):
full_restart()
add_bridge(INT_BRIDGE)
add_bridge(EXT_BRIDGE)
ext_port_ctx = ExternalPortContext()()
if ext_port_ctx is not None and ext_port_ctx['ext_port']:
add_bridge_port(EXT_BRIDGE, ext_port_ctx['ext_port'])