Added code for configurable multiple gateway interfaces.

This commit is contained in:
Bilal Ahmad 2015-09-10 03:41:10 -07:00
parent b954ff223d
commit 43b86fdff9
6 changed files with 40 additions and 28 deletions

View File

@ -36,7 +36,7 @@ This is an early access version of the PLUMgrid Gateway charm and it is not mean
Example Config Example Config
plumgrid-gateway: plumgrid-gateway:
external-interface: eth1 external-interfaces: '{"node01":"eth5,eth2","node02":"eth4,eth8"}'
install_sources: 'ppa:plumgrid-team/stable' install_sources: 'ppa:plumgrid-team/stable'
install_keys: 'null' install_keys: 'null'
plumgrid-edge: plumgrid-edge:
@ -54,7 +54,7 @@ Example Config
neutron-plugin: "plumgrid" neutron-plugin: "plumgrid"
plumgrid-virtual-ip: "192.168.100.250" plumgrid-virtual-ip: "192.168.100.250"
The "external-interface" config parameter should be the interface that will provide external connectivity. The "external-interfaces" config parameter should be the interfaces that will provide external connectivity on each of the gateway nodes. Should be provided as a json in a string with hostname and interface names.
Provide the source repo path for PLUMgrid Debs in 'install_sources' and the corresponding keys in 'install_keys'. Provide the source repo path for PLUMgrid Debs in 'install_sources' and the corresponding keys in 'install_keys'.
The virtual IP passed on in the neutron-api charm has to be same as the one passed in the plumgrid-director charm. The virtual IP passed on in the neutron-api charm has to be same as the one passed in the plumgrid-director charm.

View File

@ -1,8 +1,10 @@
options: options:
external-interface: external-interfaces:
default: eth1 default: '{"hostname":"eth1,eth2"}'
type: string type: string
description: The interface that will provide external connectivity description: |
One or multiple interfaces that will provide external connectivity on
each of the gateway nodes. Provided in form of json in a string.
lcm-ssh-key: lcm-ssh-key:
default: 'null' default: 'null'
type: string type: string

View File

@ -7,7 +7,6 @@ from charmhelpers.core.hookenv import (
relation_ids, relation_ids,
related_units, related_units,
relation_get, relation_get,
config,
) )
from charmhelpers.contrib.openstack import context from charmhelpers.contrib.openstack import context
@ -60,7 +59,6 @@ class PGGwContext(context.NeutronContext):
if not pg_ctxt: if not pg_ctxt:
return {} return {}
conf = config()
pg_dir_ips = '' pg_dir_ips = ''
pg_dir_settings = _pg_dir_settings() pg_dir_settings = _pg_dir_settings()
single_ip = True single_ip = True
@ -73,12 +71,10 @@ class PGGwContext(context.NeutronContext):
pg_ctxt['local_ip'] = pg_dir_ips pg_ctxt['local_ip'] = pg_dir_ips
unit_hostname = get_unit_hostname() unit_hostname = get_unit_hostname()
pg_ctxt['pg_hostname'] = unit_hostname pg_ctxt['pg_hostname'] = unit_hostname
from pg_gw_utils import check_interface_type from pg_gw_utils import check_interface_type, get_gw_interfaces
interface_type = check_interface_type() pg_ctxt['interface'] = check_interface_type()
pg_ctxt['interface'] = interface_type
pg_ctxt['label'] = unit_hostname pg_ctxt['label'] = unit_hostname
pg_ctxt['fabric_mode'] = 'host' pg_ctxt['fabric_mode'] = 'host'
pg_ctxt['ext_interfaces'] = get_gw_interfaces()
pg_ctxt['ext_interface'] = conf['external-interface']
return pg_ctxt return pg_ctxt

View File

@ -20,11 +20,13 @@ from collections import OrderedDict
from charmhelpers.contrib.openstack.utils import ( from charmhelpers.contrib.openstack.utils import (
os_release, os_release,
) )
from socket import gethostname as get_unit_hostname
import pg_gw_context import pg_gw_context
import subprocess import subprocess
import time import time
import os import os
import re import re
import json
LXC_CONF = "/etc/libvirt/lxc.conf" LXC_CONF = "/etc/libvirt/lxc.conf"
TEMPLATES = 'templates/' TEMPLATES = 'templates/'
@ -35,6 +37,7 @@ PG_HN_CONF = '%s/conf/etc/hostname' % PG_LXC_DATA_PATH
PG_HS_CONF = '%s/conf/etc/hosts' % PG_LXC_DATA_PATH PG_HS_CONF = '%s/conf/etc/hosts' % PG_LXC_DATA_PATH
PG_IFCS_CONF = '%s/conf/pg/ifcs.conf' % PG_LXC_DATA_PATH PG_IFCS_CONF = '%s/conf/pg/ifcs.conf' % PG_LXC_DATA_PATH
AUTH_KEY_PATH = '%s/root/.ssh/authorized_keys' % PG_LXC_DATA_PATH AUTH_KEY_PATH = '%s/root/.ssh/authorized_keys' % PG_LXC_DATA_PATH
IFC_LIST_GW = '/var/run/plumgrid/lxc/ifc_list_gateway'
SUDOERS_CONF = '/etc/sudoers.d/ifc_ctl_sudoers' SUDOERS_CONF = '/etc/sudoers.d/ifc_ctl_sudoers'
@ -103,6 +106,7 @@ def ensure_files():
write_file(SUDOERS_CONF, write_file(SUDOERS_CONF,
"\nnova ALL=(root) NOPASSWD: /opt/pg/bin/ifc_ctl_pp *\n", "\nnova ALL=(root) NOPASSWD: /opt/pg/bin/ifc_ctl_pp *\n",
owner='root', group='root', perms=0o644) owner='root', group='root', perms=0o644)
_exec_cmd(cmd=['rm', '-f', IFC_LIST_GW])
def restart_pg(): def restart_pg():
@ -155,6 +159,23 @@ def check_interface_type():
return default_interface return default_interface
def get_gw_interfaces():
'''
Gateway node can have multiple interfaces. This function parses json
provided in config to get all gateway interfaces for this node.
'''
node_interfaces = ['eth1']
try:
all_interfaces = json.loads(config('external-interfaces'))
except ValueError:
log("Invalid JSON")
return node_interfaces
hostname = get_unit_hostname()
if hostname in all_interfaces:
node_interfaces = all_interfaces[hostname].split(',')
return node_interfaces
def ensure_mtu(): def ensure_mtu():
''' '''
Ensures required MTU of the underlying networking of the node. Ensures required MTU of the underlying networking of the node.

View File

@ -1,6 +1,7 @@
{{ interface }} = fabric_core host {{ interface }} = fabric_core host
{% if ext_interface -%} {% if ext_interfaces -%}
{{ ext_interface }} = access_phys {% for ip in ext_interfaces -%}
{{ ip }} = access_phys
{% endfor -%}
{% endif -%} {% endif -%}

View File

@ -5,7 +5,6 @@ import pg_gw_utils as utils
import charmhelpers import charmhelpers
TO_PATCH = [ TO_PATCH = [
'config',
'get_unit_hostname', 'get_unit_hostname',
] ]
@ -22,8 +21,6 @@ class PGGwContextTest(CharmTestCase):
def setUp(self): def setUp(self):
super(PGGwContextTest, self).setUp(context, TO_PATCH) super(PGGwContextTest, self).setUp(context, TO_PATCH)
self.config.side_effect = self.test_config.get
self.test_config.set('external-interface', 'eth1')
def tearDown(self): def tearDown(self):
super(PGGwContextTest, self).tearDown() super(PGGwContextTest, self).tearDown()
@ -41,7 +38,9 @@ class PGGwContextTest(CharmTestCase):
@patch.object(charmhelpers.contrib.openstack.context, @patch.object(charmhelpers.contrib.openstack.context,
'neutron_plugin_attribute') 'neutron_plugin_attribute')
@patch.object(utils, 'check_interface_type') @patch.object(utils, 'check_interface_type')
def test_neutroncc_context_api_rel(self, _int_type, _npa, _pg_dir_settings, @patch.object(utils, 'get_gw_interfaces')
def test_neutroncc_context_api_rel(self, _gw_int, _int_type,
_npa, _pg_dir_settings,
_save_flag_file, _config_flag, _save_flag_file, _config_flag,
_unit_get, _unit_priv_ip, _config, _unit_get, _unit_priv_ip, _config,
_is_clus, _https, _ens_pkgs): _is_clus, _https, _ens_pkgs):
@ -50,16 +49,8 @@ class PGGwContextTest(CharmTestCase):
return "neutron.randomdriver" return "neutron.randomdriver"
if section == "config": if section == "config":
return "neutron.randomconfig" return "neutron.randomconfig"
config = {'external-interface': "eth1"}
def mock_config(key=None):
if key:
return config.get(key)
return config
self.maxDiff = None self.maxDiff = None
self.config.side_effect = mock_config
_npa.side_effect = mock_npa _npa.side_effect = mock_npa
_unit_get.return_value = '192.168.100.201' _unit_get.return_value = '192.168.100.201'
_unit_priv_ip.return_value = '192.168.100.201' _unit_priv_ip.return_value = '192.168.100.201'
@ -68,9 +59,10 @@ class PGGwContextTest(CharmTestCase):
_config_flag.return_value = False _config_flag.return_value = False
_pg_dir_settings.return_value = {'pg_dir_ip': '192.168.100.201'} _pg_dir_settings.return_value = {'pg_dir_ip': '192.168.100.201'}
_int_type.return_value = 'juju-br0' _int_type.return_value = 'juju-br0'
_gw_int.return_value = ['eth1']
napi_ctxt = context.PGGwContext() napi_ctxt = context.PGGwContext()
expect = { expect = {
'ext_interface': "eth1", 'ext_interfaces': ['eth1'],
'config': 'neutron.randomconfig', 'config': 'neutron.randomconfig',
'core_plugin': 'neutron.randomdriver', 'core_plugin': 'neutron.randomdriver',
'local_ip': 'pg_dir_ip', 'local_ip': 'pg_dir_ip',