from charmhelpers.core.hookenv import ( relation_ids, related_units, relation_get, config, unit_get, ) from charmhelpers.core.host import list_nics, get_nic_hwaddr from charmhelpers.contrib.openstack import context from charmhelpers.core.host import service_running, service_start from charmhelpers.contrib.network.ovs import add_bridge, add_bridge_port from charmhelpers.contrib.openstack.utils import get_host_ip from charmhelpers.contrib.network.ip import get_address_in_network import re OVS_BRIDGE = 'br-int' DATA_BRIDGE = 'br-data' def _neutron_security_groups(): ''' Inspects current neutron-plugin relation and determine if neutron-api has instructed us to use neutron security groups. ''' for rid in relation_ids('neutron-plugin-api'): for unit in related_units(rid): sec_group = relation_get('neutron-security-groups', rid=rid, unit=unit) if sec_group is not None: return sec_group return False class OVSPluginContext(context.NeutronContext): interfaces = [] @property def plugin(self): return 'ovs' @property def network_manager(self): return 'neutron' @property def neutron_security_groups(self): return _neutron_security_groups() 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 def _ensure_bridge(self): if not service_running('openvswitch-switch'): service_start('openvswitch-switch') add_bridge(OVS_BRIDGE) add_bridge(DATA_BRIDGE) data_port = self.get_data_port() if data_port: add_bridge_port(DATA_BRIDGE, data_port, promisc=True) 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() conf = config() ovs_ctxt['local_ip'] = \ get_address_in_network(config('os-data-network'), get_host_ip(unit_get('private-address'))) ovs_ctxt['neutron_security_groups'] = self.neutron_security_groups # TODO: We need to sort out the syslog and debug/verbose options as a # general context helper ovs_ctxt['use_syslog'] = conf['use-syslog'] ovs_ctxt['verbose'] = conf['verbose'] ovs_ctxt['debug'] = conf['debug'] return ovs_ctxt