201 lines
6.4 KiB
Python
Raw Normal View History

import os
import uuid
2014-06-05 11:59:23 +01:00
from charmhelpers.core.hookenv import (
2014-06-19 10:56:25 +01:00
relation_ids,
related_units,
relation_get,
config,
unit_get,
2014-06-05 11:59:23 +01:00
)
from charmhelpers.contrib.network.ip import (
get_address_in_network,
)
from charmhelpers.contrib.openstack.ip import resolve_address
2014-07-14 14:47:38 +03:00
from charmhelpers.core.host import list_nics, get_nic_hwaddr
from charmhelpers.core.strutils import bool_from_string
2014-06-05 11:59:23 +01:00
from charmhelpers.contrib.openstack import context
from charmhelpers.core.host import service_running, service_start
2014-07-14 14:47:38 +03:00
from charmhelpers.contrib.network.ovs import add_bridge, add_bridge_port
2014-06-05 11:59:23 +01:00
from charmhelpers.contrib.openstack.utils import get_host_ip
from charmhelpers.contrib.openstack.context import (
OSContextGenerator,
context_complete,
)
2014-06-27 14:04:10 +01:00
2014-07-14 14:47:38 +03:00
import re
2014-06-05 11:59:23 +01:00
OVS_BRIDGE = 'br-int'
2014-07-14 14:47:38 +03:00
DATA_BRIDGE = 'br-data'
2014-06-05 11:59:23 +01:00
2014-06-19 10:56:25 +01:00
def _neutron_api_settings():
2014-06-05 11:59:23 +01:00
'''
Inspects current neutron-plugin relation
2014-06-05 11:59:23 +01:00
'''
neutron_settings = {
2014-09-04 15:18:06 +00:00
'neutron_security_groups': False,
'l2_population': True,
'overlay_network_type': 'gre',
2015-02-19 15:55:06 +00:00
'enable_dvr': False,
}
for rid in relation_ids('neutron-plugin-api'):
2014-06-05 11:59:23 +01:00
for unit in related_units(rid):
rdata = relation_get(rid=rid, unit=unit)
2014-09-04 13:26:03 +00:00
if 'l2-population' not in rdata:
continue
neutron_settings = {
'l2_population': bool_from_string(rdata['l2-population']),
'overlay_network_type': rdata['overlay-network-type'],
'neutron_security_groups': bool_from_string(
rdata['neutron-security-groups']
),
}
2015-02-02 13:31:39 +00:00
if 'enable-dvr' in rdata:
2015-02-19 15:55:06 +00:00
neutron_settings['enable_dvr'] = bool_from_string(
rdata['enable-dvr']
)
# Override with configuration if set to true
if config('disable-security-groups'):
neutron_settings['neutron_security_groups'] = False
return neutron_settings
return neutron_settings
2014-06-05 11:59:23 +01:00
2014-06-19 10:56:25 +01:00
2015-02-02 13:31:39 +00:00
def use_dvr():
api_settings = _neutron_api_settings()
2015-02-19 15:55:06 +00:00
if 'enable_dvr' in api_settings:
return api_settings['enable_dvr']
else:
return False
2015-02-02 13:31:39 +00:00
2014-06-05 11:59:23 +01:00
class OVSPluginContext(context.NeutronContext):
interfaces = []
@property
def plugin(self):
return 'ovs'
@property
def network_manager(self):
return 'neutron'
@property
def neutron_security_groups(self):
neutron_api_settings = _neutron_api_settings()
2014-09-04 15:18:06 +00:00
return neutron_api_settings['neutron_security_groups']
2014-06-05 11:59:23 +01:00
2014-07-14 14:47:38 +03:00
def get_data_port(self):
data_ports = config('data-port')
if not data_ports:
return None
hwaddrs = {}
for nic in list_nics(['eth', 'bond']):
hwaddrs[get_nic_hwaddr(nic).lower()] = nic
mac_regex = re.compile(r'([0-9A-F]{2}[:-]){5}([0-9A-F]{2})', re.I)
for entry in data_ports.split():
entry = entry.strip().lower()
if re.match(mac_regex, entry):
if entry in hwaddrs:
return hwaddrs[entry]
else:
return entry
return None
2014-06-05 11:59:23 +01:00
def _ensure_bridge(self):
if not service_running('openvswitch-switch'):
service_start('openvswitch-switch')
add_bridge(OVS_BRIDGE)
2014-07-14 14:47:38 +03:00
add_bridge(DATA_BRIDGE)
data_port = self.get_data_port()
if data_port:
add_bridge_port(DATA_BRIDGE, data_port, promisc=True)
2014-06-05 11:59:23 +01:00
def ovs_ctxt(self):
# In addition to generating config context, ensure the OVS service
# is running and the OVS bridge exists. Also need to ensure
# local_ip points to actual IP, not hostname.
ovs_ctxt = super(OVSPluginContext, self).ovs_ctxt()
if not ovs_ctxt:
return {}
self._ensure_bridge()
2014-06-05 14:16:54 +00:00
conf = config()
2014-06-27 14:04:10 +01:00
ovs_ctxt['local_ip'] = \
get_address_in_network(config('os-data-network'),
get_host_ip(unit_get('private-address')))
neutron_api_settings = _neutron_api_settings()
2014-09-04 15:18:06 +00:00
ovs_ctxt['neutron_security_groups'] = self.neutron_security_groups
ovs_ctxt['l2_population'] = neutron_api_settings['l2_population']
2015-02-02 13:31:39 +00:00
ovs_ctxt['distributed_routing'] = use_dvr()
2014-10-02 14:02:42 +00:00
ovs_ctxt['overlay_network_type'] = \
neutron_api_settings['overlay_network_type']
2014-06-23 12:49:58 +01:00
# TODO: We need to sort out the syslog and debug/verbose options as a
# general context helper
2014-06-05 14:16:54 +00:00
ovs_ctxt['use_syslog'] = conf['use-syslog']
2014-06-17 15:31:03 +01:00
ovs_ctxt['verbose'] = conf['verbose']
ovs_ctxt['debug'] = conf['debug']
2014-06-05 11:59:23 +01:00
return ovs_ctxt
2015-02-02 13:31:39 +00:00
class L3AgentContext(OSContextGenerator):
def __call__(self):
neutron_api_settings = _neutron_api_settings()
ctxt = {}
if neutron_api_settings['enable_dvr']:
2015-02-02 13:31:39 +00:00
ctxt['agent_mode'] = 'dvr'
else:
ctxt['agent_mode'] = 'legacy'
return ctxt
class NetworkServiceContext(OSContextGenerator):
interfaces = ['neutron-network-service']
def __call__(self):
for rid in relation_ids('neutron-network-service'):
for unit in related_units(rid):
rdata = relation_get(rid=rid, unit=unit)
ctxt = {
'service_protocol':
rdata.get('service_protocol') or 'http',
'keystone_host': rdata.get('keystone_host'),
'service_port': rdata.get('service_port'),
'region': rdata.get('region'),
'service_tenant': rdata.get('service_tenant'),
'service_username': rdata.get('service_username'),
'service_password': rdata.get('service_password'),
}
if context_complete(ctxt):
return ctxt
2015-02-25 13:50:38 +00:00
SHARED_SECRET = "/etc/neutron/secret.txt"
2015-02-25 13:50:38 +00:00
def get_shared_secret():
secret = None
if not os.path.exists(SHARED_SECRET):
secret = str(uuid.uuid4())
with open(SHARED_SECRET, 'w') as secret_file:
secret_file.write(secret)
else:
with open(SHARED_SECRET, 'r') as secret_file:
secret = secret_file.read().strip()
return secret
class DVRSharedSecretContext(OSContextGenerator):
def __call__(self):
if use_dvr():
ctxt = {
2015-02-25 13:50:38 +00:00
'shared_secret': get_shared_secret(),
'local_ip': resolve_address(),
}
else:
ctxt = {}
return ctxt