components/openstack/neutron/files/agent/solaris/ra.py
author Girish Moodalbail <Girish.Moodalbail@oracle.COM>
Fri, 16 Oct 2015 15:53:02 -0700
changeset 4975 6445e44cfccd
parent 3998 5bd484384122
child 5405 66fd59fecd68
permissions -rw-r--r--
21978756 addrconf addresses must be created for stateless and slaac Neutron subnets 21978743 ndpd.conf entries are incorrectly formatted for IPv6 subnets 21919000 neutron-dhcp-agent and neutron-server have timing issues 21918991 database times out when attempting various actions 21682493 Neutron fails due to mysql transaction locks when creating multiple instances 22024767 Remove annoying "Arguments dropped when creating context" logging

# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2014 OpenStack Foundation
# All Rights Reserved.
#
# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import jinja2
import netaddr
from oslo.config import cfg
import six

from neutron.agent.linux import utils
from neutron.common import constants
from neutron.openstack.common import log as logging


LOG = logging.getLogger(__name__)

OPTS = [
    cfg.StrOpt('ra_confs',
               default='$state_path/ra',
               help=_('Location to store IPv6 RA config files')),
]

cfg.CONF.register_opts(OPTS)

NDP_SMF_FMRI = 'svc:/network/routing/ndp:default'

# The configuration file for ndpd daemon expects all the 'key value' to be
# on the same line as that of the interface. For example:
#
# if net0  AdvSendAdvertisements on MinRtrAdvInterval 3 MaxRtrAdvInterval 10
# prefix 3234234 net0 AdvOnLinkFlag on AdvAutonomousFlag on
CONFIG_TEMPLATE = jinja2.Template(
    """if {{ interface_name }} """
    """ AdvSendAdvertisements on MinRtrAdvInterval 3 MaxRtrAdvInterval 10 """
    """ {% if ra_mode == constants.DHCPV6_STATELESS %} """
    """ AdvOtherConfigFlag on """
    """ {% endif %} """
    """ {% if ra_mode == constants.DHCPV6_STATEFUL %} """
    """ AdvManagedFlag on """
    """ {% endif %} """
    """ {% if ra_mode in (constants.IPV6_SLAAC, """
    """ constants.DHCPV6_STATELESS) %} """
    """\nprefix {{ prefix }} {{ interface_name }} """
    """ AdvOnLinkFlag on AdvAutonomousFlag on """
    """ {% endif %} """)


def _generate_ndpd_conf(router_id, router_ports, dev_name_helper):
    ndpd_conf = utils.get_conf_file_name(cfg.CONF.ra_confs, router_id,
                                         'ndpd.conf', True)
    buf = six.StringIO()
    for p in router_ports:
        prefix = p['subnet']['cidr']
        if netaddr.IPNetwork(prefix).version == 6:
            interface_name = dev_name_helper(p['id'])
            ra_mode = p['subnet']['ipv6_ra_mode']
            buf.write('%s\n' % CONFIG_TEMPLATE.render(
                ra_mode=ra_mode,
                interface_name=interface_name,
                prefix=prefix,
                constants=constants))

    utils.replace_file(ndpd_conf, buf.getvalue())
    return ndpd_conf


def _refresh_ndpd(ndpd_conf):
    cmd = ['/usr/sbin/svccfg', '-s', NDP_SMF_FMRI, 'setprop',
           'routing/config_file', '=', ndpd_conf]
    utils.execute(cmd)
    # this is needed to reflect the routing/config_file property
    # in svcprop output
    cmd = ['/usr/sbin/svccfg', '-s', NDP_SMF_FMRI, 'refresh']
    utils.execute(cmd)
    # ndpd SMF service doesn't support refresh method, so we
    # need to restart
    cmd = ['/usr/sbin/svcadm', 'restart', NDP_SMF_FMRI]
    utils.execute(cmd)
    LOG.debug(_("ndpd daemon has been refreshed to re-read the "
                "configuration file"))


def enable_ipv6_ra(router_id, router_ports, dev_name_helper):
    for p in router_ports:
        if netaddr.IPNetwork(p['subnet']['cidr']).version == 6:
            break
    else:
        disable_ipv6_ra(router_id)
        return
    LOG.debug("enabling ndpd for router %s", router_id)
    ndpd_conf = _generate_ndpd_conf(router_id, router_ports, dev_name_helper)
    _refresh_ndpd(ndpd_conf)


def disable_ipv6_ra(router_id):
    LOG.debug("disabling ndpd for router %s", router_id)
    utils.remove_conf_files(cfg.CONF.ra_confs, router_id)
    _refresh_ndpd("")