diff --git a/config.yaml b/config.yaml index c450253..7782791 100644 --- a/config.yaml +++ b/config.yaml @@ -25,7 +25,7 @@ options: type: string description: | Interfaces that will provide fabric connectivity on the director nodes. - Provided in form of json in a string. These interfaces have to be connected + Provided in form of json in a string. These interfaces have to be connected to the os-data-network specified in the config. Default value is MANAGEMENT which will configure the management interface as the fabric interface on each director. @@ -55,3 +55,7 @@ options: default: null type: string description: Provide the PLUMgrid ONS License key. + opsvm-ip: + default: 127.0.0.1 + type: string + description: IP address of the PLUMgrid Operations VM Management interface. diff --git a/hooks/pg_dir_context.py b/hooks/pg_dir_context.py index fb3c5f8..1a03fe9 100644 --- a/hooks/pg_dir_context.py +++ b/hooks/pg_dir_context.py @@ -31,12 +31,11 @@ def _pg_dir_ips(): Inspects plumgrid-director peer relation and returns the ips of the peer directors ''' - pg_dir_ips = [] - for rid in relation_ids('director'): - for unit in related_units(rid): - rdata = relation_get(rid=rid, unit=unit) - pg_dir_ips.append(get_host_ip(rdata['private-address'])) - return pg_dir_ips + return [get_host_ip(rdata['private-address']) + for rid in relation_ids("director") + for rdata in + (relation_get(rid=rid, unit=unit) for unit in related_units(rid)) + if rdata] class PGDirContext(context.NeutronContext): @@ -79,18 +78,15 @@ class PGDirContext(context.NeutronContext): fallback=get_host_ip(unit_get('private-address'))))) pg_dir_ips = sorted(pg_dir_ips) pg_ctxt['director_ips'] = pg_dir_ips - pg_dir_ips_string = '' - single_ip = True - for ip in pg_dir_ips: - if single_ip: - pg_dir_ips_string = str(ip) - single_ip = False - else: - pg_dir_ips_string = pg_dir_ips_string + ',' + str(ip) - pg_ctxt['director_ips_string'] = pg_dir_ips_string - PG_VIP = config('plumgrid-virtual-ip') + dir_count = len(pg_dir_ips) + pg_ctxt['director_ips_string'] = (str(pg_dir_ips[0]) + ',' + + str(pg_dir_ips[1]) + ',' + + str(pg_dir_ips[2]) + if dir_count == 3 else + str(pg_dir_ips[0])) + PG_VIP = conf['plumgrid-virtual-ip'] if is_ip(PG_VIP): - pg_ctxt['virtual_ip'] = conf['plumgrid-virtual-ip'] + pg_ctxt['virtual_ip'] = PG_VIP else: raise ValueError('Invalid PLUMgrid Virtual IP Provided') unit_hostname = gethostname() @@ -103,5 +99,6 @@ class PGDirContext(context.NeutronContext): pg_ctxt['fabric_mode'] = 'host' virtual_ip_array = re.split('\.', conf['plumgrid-virtual-ip']) pg_ctxt['virtual_router_id'] = virtual_ip_array[3] + pg_ctxt['opsvm_ip'] = conf['opsvm-ip'] return pg_ctxt diff --git a/hooks/pg_dir_hooks.py b/hooks/pg_dir_hooks.py index 94b547c..2476136 100755 --- a/hooks/pg_dir_hooks.py +++ b/hooks/pg_dir_hooks.py @@ -8,23 +8,26 @@ import sys import time from charmhelpers.core.host import service_running +from charmhelpers.contrib.network.ip import is_ip from charmhelpers.core.hookenv import ( Hooks, UnregisteredHookError, log, config, + relation_set, + relation_ids ) from charmhelpers.fetch import ( apt_install, - apt_purge, configure_sources, ) from pg_dir_utils import ( register_configs, restart_pg, + restart_map, stop_pg, determine_packages, load_iovisor, @@ -33,7 +36,9 @@ from pg_dir_utils import ( add_lcm_key, post_pg_license, fabric_interface_changed, - load_iptables + load_iptables, + restart_on_change, + director_cluster_ready ) hooks = Hooks() @@ -56,12 +61,26 @@ def install(): @hooks.hook('director-relation-joined') +@restart_on_change(restart_map()) def dir_joined(): ''' This hook is run when a unit of director is added. ''' - CONFIGS.write_all() - restart_pg() + if director_cluster_ready(): + ensure_mtu() + CONFIGS.write_all() + + +@hooks.hook('plumgrid-relation-joined') +def plumgrid_joined(relation_id=None): + ''' + This hook is run when relation with edge or gateway is created. + ''' + opsvm_ip = config('opsvm-ip') + if not is_ip(opsvm_ip): + raise ValueError('Incorrect OPSVM IP specified') + else: + relation_set(relation_id=relation_id, opsvm_ip=opsvm_ip) @hooks.hook('config-changed') @@ -96,6 +115,10 @@ def config_changed(): apt_install(pkg, options=['--force-yes'], fatal=True) remove_iovisor() load_iovisor() + if charm_config.changed('opsvm-ip'): + for rid in relation_ids('plumgrid'): + plumgrid_joined(rid) + stop_pg() ensure_mtu() CONFIGS.write_all() if not service_running('plumgrid'): @@ -112,16 +135,17 @@ def start(): while (count < 10): if post_pg_license(): break - count = count + 1 + count += 1 time.sleep(15) @hooks.hook('upgrade-charm') +@restart_on_change(restart_map()) def upgrade_charm(): ''' This hook is run when the charm is upgraded ''' - load_iptables() + ensure_mtu() CONFIGS.write_all() @@ -131,10 +155,6 @@ def stop(): This hook is run when the charm is destroyed. ''' stop_pg() - remove_iovisor() - pkgs = determine_packages() - for pkg in pkgs: - apt_purge(pkg, fatal=False) def main(): diff --git a/hooks/pg_dir_utils.py b/hooks/pg_dir_utils.py index 697ecbf..cc9c5bc 100644 --- a/hooks/pg_dir_utils.py +++ b/hooks/pg_dir_utils.py @@ -12,7 +12,6 @@ from socket import gethostname as get_unit_hostname from copy import deepcopy from charmhelpers.contrib.openstack.neutron import neutron_plugin_attribute from charmhelpers.contrib.openstack import templating -from charmhelpers.core.host import set_nic_mtu from charmhelpers.contrib.storage.linux.ceph import modprobe from charmhelpers.core.hookenv import ( log, @@ -30,7 +29,9 @@ from charmhelpers.contrib.network.ip import ( from charmhelpers.core.host import ( service_start, service_stop, - service_running + service_running, + path_hash, + set_nic_mtu ) from charmhelpers.fetch import ( apt_cache, @@ -50,6 +51,7 @@ PG_DEF_CONF = '%s/conf/pg/nginx.conf' % PG_LXC_DATA_PATH PG_HN_CONF = '%s/conf/etc/hostname' % 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 +OPS_CONF = '%s/conf/etc/00-pg.conf' % PG_LXC_DATA_PATH AUTH_KEY_PATH = '%s/root/.ssh/authorized_keys' % PG_LXC_DATA_PATH TEMP_LICENSE_FILE = '/tmp/license' @@ -74,6 +76,10 @@ BASE_RESOURCE_MAP = OrderedDict([ 'services': ['plumgrid'], 'contexts': [pg_dir_context.PGDirContext()], }), + (OPS_CONF, { + 'services': ['plumgrid'], + 'contexts': [pg_dir_context.PGDirContext()], + }), (PG_IFCS_CONF, { 'services': [], 'contexts': [pg_dir_context.PGDirContext()], @@ -401,3 +407,24 @@ def get_cidr_from_iface(interface): return None else: return None + + +def director_cluster_ready(): + dirs_count = len(pg_dir_context._pg_dir_ips()) + return True if dirs_count == 2 else False + + +def restart_on_change(restart_map): + """ + Restart services based on configuration files changing + """ + def wrap(f): + def wrapped_f(*args, **kwargs): + checksums = {path: path_hash(path) for path in restart_map} + f(*args, **kwargs) + for path in restart_map: + if path_hash(path) != checksums[path]: + restart_pg() + break + return wrapped_f + return wrap diff --git a/hooks/plumgrid-relation-joined b/hooks/plumgrid-relation-joined new file mode 120000 index 0000000..6530c5a --- /dev/null +++ b/hooks/plumgrid-relation-joined @@ -0,0 +1 @@ +pg_dir_hooks.py \ No newline at end of file diff --git a/templates/kilo/00-pg.conf b/templates/kilo/00-pg.conf new file mode 100644 index 0000000..c5a6016 --- /dev/null +++ b/templates/kilo/00-pg.conf @@ -0,0 +1 @@ +$template ls_json,"{{'{'}}{{'%'}}timestamp:::date-rfc3339,jsonf:@timestamp%,%source:::jsonf:@source_host%,%msg:::json%}":syslogtag,isequal,"pg:" @{{ opsvm_ip }}:6000;ls_json diff --git a/templates/kilo/nginx.conf b/templates/kilo/nginx.conf index 00f58f1..7f5c51b 100644 --- a/templates/kilo/nginx.conf +++ b/templates/kilo/nginx.conf @@ -13,7 +13,7 @@ upstream pgCli { } upstream pgMW { - server 127.0.0.1:4000; + server {{ opsvm_ip }}:4000; } map $http_upgrade $connection_upgrade { diff --git a/unit_tests/test_pg_dir_context.py b/unit_tests/test_pg_dir_context.py index 9d32722..84a29b2 100644 --- a/unit_tests/test_pg_dir_context.py +++ b/unit_tests/test_pg_dir_context.py @@ -59,7 +59,8 @@ class PGDirContextTest(CharmTestCase): if section == "config": return "neutron.randomconfig" - config = {'plumgrid-virtual-ip': "192.168.100.250"} + config = {'plumgrid-virtual-ip': "192.168.100.250", + 'opsvm-ip': '127.0.0.1'} def mock_config(key=None): if key: @@ -99,5 +100,6 @@ class PGDirContextTest(CharmTestCase): '192.168.100.203'], 'director_ips_string': '192.168.100.201,192.168.100.202,192.168.100.203', + 'opsvm_ip': '127.0.0.1', } self.assertEquals(expect, napi_ctxt()) diff --git a/unit_tests/test_pg_dir_hooks.py b/unit_tests/test_pg_dir_hooks.py index c453ca8..1b8e5e8 100644 --- a/unit_tests/test_pg_dir_hooks.py +++ b/unit_tests/test_pg_dir_hooks.py @@ -20,7 +20,6 @@ utils.restart_map = _map TO_PATCH = [ 'remove_iovisor', 'apt_install', - 'apt_purge', 'CONFIGS', 'log', 'configure_sources', @@ -67,8 +66,5 @@ class PGDirHooksTests(CharmTestCase): self.test_config.set('plumgrid-license-key', None) def test_stop(self): - _pkgs = ['plumgrid-lxc', 'iovisor-dkms'] self._call_hook('stop') self.stop_pg.assert_called_with() - self.remove_iovisor.assert_called_with() - self.determine_packages.return_value = _pkgs diff --git a/unit_tests/test_pg_dir_utils.py b/unit_tests/test_pg_dir_utils.py index d4fe0b1..4e0741e 100644 --- a/unit_tests/test_pg_dir_utils.py +++ b/unit_tests/test_pg_dir_utils.py @@ -55,7 +55,8 @@ class TestPGDirUtils(CharmTestCase): nutils.PG_DEF_CONF, nutils.PG_HN_CONF, nutils.PG_HS_CONF, - nutils.PG_IFCS_CONF] + nutils.PG_IFCS_CONF, + nutils.OPS_CONF] self.assertItemsEqual(_regconfs.configs, confs) def test_resource_map(self): @@ -73,6 +74,7 @@ class TestPGDirUtils(CharmTestCase): (nutils.PG_DEF_CONF, ['plumgrid']), (nutils.PG_HN_CONF, ['plumgrid']), (nutils.PG_HS_CONF, ['plumgrid']), + (nutils.OPS_CONF, ['plumgrid']), (nutils.PG_IFCS_CONF, []), ]) self.assertEqual(expect, _restart_map)