3998N/A# vim: tabstop=4 shiftwidth=4 softtabstop=4
3998N/A
3998N/A# Copyright 2014 OpenStack Foundation
3998N/A# All Rights Reserved.
3998N/A#
3998N/A# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3998N/A#
3998N/A# Licensed under the Apache License, Version 2.0 (the "License"); you may
3998N/A# not use this file except in compliance with the License. You may obtain
3998N/A# a copy of the License at
3998N/A#
3998N/A# http://www.apache.org/licenses/LICENSE-2.0
3998N/A#
3998N/A# Unless required by applicable law or agreed to in writing, software
3998N/A# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
3998N/A# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
3998N/A# License for the specific language governing permissions and limitations
3998N/A# under the License.
3998N/A
3998N/Aimport jinja2
3998N/Aimport netaddr
5403N/Afrom oslo_config import cfg
5403N/Afrom oslo_log import log as logging
3998N/Aimport six
3998N/A
3998N/Afrom neutron.agent.linux import utils
3998N/Afrom neutron.common import constants
3998N/A
3998N/A
3998N/ALOG = logging.getLogger(__name__)
3998N/A
3998N/AOPTS = [
3998N/A cfg.StrOpt('ra_confs',
3998N/A default='$state_path/ra',
3998N/A help=_('Location to store IPv6 RA config files')),
3998N/A]
3998N/A
3998N/Acfg.CONF.register_opts(OPTS)
3998N/A
3998N/ANDP_SMF_FMRI = 'svc:/network/routing/ndp:default'
3998N/A
4973N/A# The configuration file for ndpd daemon expects all the 'key value' to be
4973N/A# on the same line as that of the interface. For example:
4973N/A#
4973N/A# if net0 AdvSendAdvertisements on MinRtrAdvInterval 3 MaxRtrAdvInterval 10
4973N/A# prefix 3234234 net0 AdvOnLinkFlag on AdvAutonomousFlag on
4973N/ACONFIG_TEMPLATE = jinja2.Template(
4973N/A """if {{ interface_name }} """
4973N/A """ AdvSendAdvertisements on MinRtrAdvInterval 3 MaxRtrAdvInterval 10 """
4973N/A """ {% if ra_mode == constants.DHCPV6_STATELESS %} """
4973N/A """ AdvOtherConfigFlag on """
4973N/A """ {% endif %} """
4973N/A """ {% if ra_mode == constants.DHCPV6_STATEFUL %} """
4973N/A """ AdvManagedFlag on """
4973N/A """ {% endif %} """
4973N/A """ {% if ra_mode in (constants.IPV6_SLAAC, """
4973N/A """ constants.DHCPV6_STATELESS) %} """
4973N/A """\nprefix {{ prefix }} {{ interface_name }} """
4973N/A """ AdvOnLinkFlag on AdvAutonomousFlag on """
4973N/A """ {% endif %} """)
3998N/A
3998N/A
5403N/Aclass NDPD(object):
5403N/A """Manage the data and state of Solaris in.ndpd daemon"""
5403N/A
5403N/A def __init__(self, router_id, dev_name_helper):
5403N/A self._router_id = router_id
5403N/A self._dev_name_helper = dev_name_helper
3998N/A
5403N/A def _generate_ndpd_conf(self, router_ports):
5403N/A ndpd_conf = utils.get_conf_file_name(cfg.CONF.ra_confs,
5403N/A self._router_id,
5403N/A 'ndpd.conf', True)
5403N/A buf = six.StringIO()
5403N/A for p in router_ports:
5403N/A prefix = p['subnets'][0]['cidr']
5403N/A if netaddr.IPNetwork(prefix).version == 6:
5403N/A interface_name = self._dev_name_helper(p['id'])
5403N/A ra_mode = p['subnets'][0]['ipv6_ra_mode']
5403N/A buf.write('%s\n' % CONFIG_TEMPLATE.render(
5403N/A ra_mode=ra_mode,
5403N/A interface_name=interface_name,
5403N/A prefix=prefix,
5403N/A constants=constants))
3998N/A
5403N/A utils.replace_file(ndpd_conf, buf.getvalue())
5403N/A return ndpd_conf
3998N/A
5403N/A def _refresh_ndpd(self, ndpd_conf):
5403N/A cmd = ['/usr/sbin/svccfg', '-s', NDP_SMF_FMRI, 'setprop',
5403N/A 'routing/config_file', '=', ndpd_conf]
5403N/A utils.execute(cmd)
5403N/A cmd = ['/usr/sbin/svccfg', '-s', NDP_SMF_FMRI, 'refresh']
5403N/A utils.execute(cmd)
5403N/A # ndpd SMF service doesn't support refresh method, so we
5403N/A # need to restart
5403N/A cmd = ['/usr/sbin/svcadm', 'restart', NDP_SMF_FMRI]
5403N/A utils.execute(cmd)
5403N/A LOG.debug(_("ndpd daemon has been refreshed to re-read the "
5403N/A "configuration file"))
3998N/A
5403N/A def enable(self, router_ports):
5403N/A for p in router_ports:
5403N/A if netaddr.IPNetwork(p['subnets'][0]['cidr']).version == 6:
5403N/A break
5403N/A else:
5403N/A self.disable()
5403N/A return
5403N/A LOG.debug("enabling ndpd for router %s", self._router_id)
5403N/A ndpd_conf = self._generate_ndpd_conf(router_ports)
5403N/A self._refresh_ndpd(ndpd_conf)
3998N/A
5403N/A def disable(self):
5403N/A LOG.debug("disabling ndpd for router %s", self._router_id)
5403N/A utils.remove_conf_files(cfg.CONF.ra_confs, self._router_id)
5403N/A self._refresh_ndpd("")
3998N/A
5403N/A @property
5403N/A def enabled(self):
5403N/A cmd = ['/usr/bin/svcs', '-H', '-o', 'state', NDP_SMF_FMRI]
5403N/A stdout = utils.execute(cmd)
5403N/A return 'online' in stdout