--- /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