components/openstack/neutron/patches/02-dhcp-agent-add-solaris.patch
branchs11-update
changeset 3028 5e73a3a3f66a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/openstack/neutron/patches/02-dhcp-agent-add-solaris.patch	Mon Mar 31 16:44:02 2014 -0700
@@ -0,0 +1,251 @@
+In-house patch to split out the Linux specific implementation details of the
+Neutron DHCP agent into a separate module. This allows for a common
+main DHCP agent module on different platforms.  This patch has not yet
+been submitted upstream.
+
+--- quantum-2013.1.4/quantum/agent/dhcp_agent.py.~1~	2013-10-17 11:24:18.000000000 -0700
++++ quantum-2013.1.4/quantum/agent/dhcp_agent.py	2014-03-13 01:37:26.539103862 -0700
+@@ -17,7 +17,6 @@
+ 
+ import os
+ import socket
+-import uuid
+ 
+ import eventlet
+ import netaddr
+@@ -26,11 +25,8 @@
+ from quantum.agent.common import config
+ from quantum.agent.linux import dhcp
+ from quantum.agent.linux import external_process
+-from quantum.agent.linux import interface
+-from quantum.agent.linux import ip_lib
+ from quantum.agent import rpc as agent_rpc
+ from quantum.common import constants
+-from quantum.common import exceptions
+ from quantum.common import topics
+ from quantum import context
+ from quantum import manager
+@@ -58,6 +54,9 @@
+         cfg.StrOpt('dhcp_driver',
+                    default='quantum.agent.linux.dhcp.Dnsmasq',
+                    help=_("The driver used to manage the DHCP server.")),
++        cfg.StrOpt('devicemanager',
++                   default='quantum.agent.linux.device.DeviceManager',
++                   help=_("The driver to manage OS specific devices.")),
+         cfg.BoolOpt('use_namespaces', default=True,
+                     help=_("Allow overlapping IP.")),
+         cfg.BoolOpt('enable_isolated_metadata', default=False,
+@@ -77,7 +76,9 @@
+         self.dhcp_driver_cls = importutils.import_class(self.conf.dhcp_driver)
+         ctx = context.get_admin_context_without_session()
+         self.plugin_rpc = DhcpPluginApi(topics.PLUGIN, ctx)
+-        self.device_manager = DeviceManager(self.conf, self.plugin_rpc)
++        self.device_manager = \
++            importutils.import_object(self.conf.devicemanager,
++                                      self.conf, self.plugin_rpc)
+         self.lease_relay = DhcpLeaseRelay(self.update_lease)
+ 
+         self.dhcp_version = self.dhcp_driver_cls.check_version()
+@@ -494,167 +495,6 @@
+                 'ports': num_ports}
+ 
+ 
+-class DeviceManager(object):
+-    OPTS = [
+-        cfg.StrOpt('interface_driver',
+-                   help=_("The driver used to manage the virtual interface."))
+-    ]
+-
+-    def __init__(self, conf, plugin):
+-        self.conf = conf
+-        self.root_helper = config.get_root_helper(conf)
+-        self.plugin = plugin
+-        if not conf.interface_driver:
+-            raise SystemExit(_('You must specify an interface driver'))
+-        try:
+-            self.driver = importutils.import_object(conf.interface_driver,
+-                                                    conf)
+-        except:
+-            msg = _("Error importing interface driver "
+-                    "'%s'") % conf.interface_driver
+-            raise SystemExit(msg)
+-
+-    def get_interface_name(self, network, port=None):
+-        """Return interface(device) name for use by the DHCP process."""
+-        if not port:
+-            device_id = self.get_device_id(network)
+-            port = self.plugin.get_dhcp_port(network.id, device_id)
+-        return self.driver.get_device_name(port)
+-
+-    def get_device_id(self, network):
+-        """Return a unique DHCP device ID for this host on the network."""
+-        # There could be more than one dhcp server per network, so create
+-        # a device id that combines host and network ids
+-
+-        host_uuid = uuid.uuid5(uuid.NAMESPACE_DNS, socket.gethostname())
+-        return 'dhcp%s-%s' % (host_uuid, network.id)
+-
+-    def _get_device(self, network):
+-        """Return DHCP ip_lib device for this host on the network."""
+-        device_id = self.get_device_id(network)
+-        port = self.plugin.get_dhcp_port(network.id, device_id)
+-        interface_name = self.get_interface_name(network, port)
+-        namespace = NS_PREFIX + network.id
+-        return ip_lib.IPDevice(interface_name,
+-                               self.root_helper,
+-                               namespace)
+-
+-    def _set_default_route(self, network):
+-        """Sets the default gateway for this dhcp namespace.
+-
+-        This method is idempotent and will only adjust the route if adjusting
+-        it would change it from what it already is.  This makes it safe to call
+-        and avoids unnecessary perturbation of the system.
+-        """
+-        device = self._get_device(network)
+-        gateway = device.route.get_gateway()
+-
+-        for subnet in network.subnets:
+-            skip_subnet = (
+-                subnet.ip_version != 4
+-                or not subnet.enable_dhcp
+-                or subnet.gateway_ip is None)
+-
+-            if skip_subnet:
+-                continue
+-
+-            if gateway != subnet.gateway_ip:
+-                m = _('Setting gateway for dhcp netns on net %(n)s to %(ip)s')
+-                LOG.debug(m, {'n': network.id, 'ip': subnet.gateway_ip})
+-
+-                device.route.add_gateway(subnet.gateway_ip)
+-
+-            return
+-
+-        # No subnets on the network have a valid gateway.  Clean it up to avoid
+-        # confusion from seeing an invalid gateway here.
+-        if gateway is not None:
+-            msg = _('Removing gateway for dhcp netns on net %s')
+-            LOG.debug(msg, network.id)
+-
+-            device.route.delete_gateway(gateway)
+-
+-    def setup(self, network, reuse_existing=False):
+-        """Create and initialize a device for network's DHCP on this host."""
+-        device_id = self.get_device_id(network)
+-        port = self.plugin.get_dhcp_port(network.id, device_id)
+-
+-        interface_name = self.get_interface_name(network, port)
+-
+-        if self.conf.use_namespaces:
+-            namespace = NS_PREFIX + network.id
+-        else:
+-            namespace = None
+-
+-        if ip_lib.device_exists(interface_name,
+-                                self.root_helper,
+-                                namespace):
+-            if not reuse_existing:
+-                raise exceptions.PreexistingDeviceFailure(
+-                    dev_name=interface_name)
+-
+-            LOG.debug(_('Reusing existing device: %s.'), interface_name)
+-        else:
+-            self.driver.plug(network.id,
+-                             port.id,
+-                             interface_name,
+-                             port.mac_address,
+-                             namespace=namespace)
+-        ip_cidrs = []
+-        for fixed_ip in port.fixed_ips:
+-            subnet = fixed_ip.subnet
+-            net = netaddr.IPNetwork(subnet.cidr)
+-            ip_cidr = '%s/%s' % (fixed_ip.ip_address, net.prefixlen)
+-            ip_cidrs.append(ip_cidr)
+-
+-        if (self.conf.enable_isolated_metadata and
+-            self.conf.use_namespaces):
+-            ip_cidrs.append(METADATA_DEFAULT_IP)
+-
+-        self.driver.init_l3(interface_name, ip_cidrs,
+-                            namespace=namespace)
+-
+-        # ensure that the dhcp interface is first in the list
+-        if namespace is None:
+-            device = ip_lib.IPDevice(interface_name,
+-                                     self.root_helper)
+-            device.route.pullup_route(interface_name)
+-
+-        if self.conf.enable_metadata_network:
+-            meta_cidr = netaddr.IPNetwork(METADATA_DEFAULT_IP)
+-            metadata_subnets = [s for s in network.subnets if
+-                                netaddr.IPNetwork(s.cidr) in meta_cidr]
+-            if metadata_subnets:
+-                # Add a gateway so that packets can be routed back to VMs
+-                device = ip_lib.IPDevice(interface_name,
+-                                         self.root_helper,
+-                                         namespace)
+-                # Only 1 subnet on metadata access network
+-                gateway_ip = metadata_subnets[0].gateway_ip
+-                device.route.add_gateway(gateway_ip)
+-        elif self.conf.use_namespaces:
+-            self._set_default_route(network)
+-
+-        return interface_name
+-
+-    def update(self, network):
+-        """Update device settings for the network's DHCP on this host."""
+-        if self.conf.use_namespaces and not self.conf.enable_metadata_network:
+-            self._set_default_route(network)
+-
+-    def destroy(self, network, device_name):
+-        """Destroy the device used for the network's DHCP on this host."""
+-        if self.conf.use_namespaces:
+-            namespace = NS_PREFIX + network.id
+-        else:
+-            namespace = None
+-
+-        self.driver.unplug(device_name, namespace=namespace)
+-
+-        self.plugin.release_dhcp_port(network.id,
+-                                      self.get_device_id(network))
+-
+-
+ class DictModel(object):
+     """Convert dict into an object that provides attribute access to values."""
+     def __init__(self, d):
+@@ -783,11 +623,11 @@
+     cfg.CONF.register_opts(DhcpAgent.OPTS)
+     config.register_agent_state_opts_helper(cfg.CONF)
+     config.register_root_helper(cfg.CONF)
+-    cfg.CONF.register_opts(DeviceManager.OPTS)
+     cfg.CONF.register_opts(DhcpLeaseRelay.OPTS)
+     cfg.CONF.register_opts(dhcp.OPTS)
+-    cfg.CONF.register_opts(interface.OPTS)
+     cfg.CONF(project='quantum')
++    if not cfg.CONF.devicemanager:
++        raise SystemExit(_('You must specify a devicemanager'))
+     config.setup_logging(cfg.CONF)
+     server = quantum_service.Service.create(
+         binary='quantum-dhcp-agent',
+--- quantum-2013.1.4/quantum/db/dhcp_rpc_base.py.~1~	2013-10-17 11:24:18.000000000 -0700
++++ quantum-2013.1.4/quantum/db/dhcp_rpc_base.py	2014-03-13 01:27:46.731450967 -0700
+@@ -97,11 +97,14 @@
+                 for fixed_ip in port['fixed_ips']:
+                     if fixed_ip['subnet_id'] in dhcp_enabled_subnet_ids:
+                         dhcp_enabled_subnet_ids.remove(fixed_ip['subnet_id'])
+-                port['fixed_ips'].extend(
+-                    [dict(subnet_id=s) for s in dhcp_enabled_subnet_ids])
++                if dhcp_enabled_subnet_ids:
++                    port['fixed_ips'].extend(
++                        [dict(subnet_id=s) for s in dhcp_enabled_subnet_ids])
+ 
+-                retval = plugin.update_port(context, port['id'],
+-                                            dict(port=port))
++                    retval = plugin.update_port(context, port['id'],
++                                                dict(port=port))
++                else:
++                    retval = port
+ 
+         except exc.NoResultFound:
+             pass