Browse Source

Merge remote-tracking branch 'origin' into merge-branch

This commit merges the master neutron branch into the feature/lbaasv2
branch. This is needed to get the feature/lbaasv2 branch building again.

Change-Id: Iba59aa20adc6b369b4b9d250afee406159287ba1
changes/64/130864/2
Kyle Mestery 8 years ago
parent
commit
c089154a94
  1. 124
      .pylintrc
  2. 1
      HACKING.rst
  3. 9
      doc/source/devref/db_layer.rst
  4. 9
      etc/neutron.conf
  5. 15
      etc/neutron/plugins/cisco/cisco_cfg_agent.ini
  6. 63
      etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini
  7. 3
      etc/neutron/rootwrap.d/l3.filters
  8. 14
      neutron/agent/__init__.py
  9. 14
      neutron/agent/common/__init__.py
  10. 9
      neutron/agent/common/config.py
  11. 14
      neutron/agent/firewall.py
  12. 4
      neutron/agent/l2population_rpc.py
  13. 212
      neutron/agent/l3_agent.py
  14. 14
      neutron/agent/linux/__init__.py
  15. 3
      neutron/agent/linux/dhcp.py
  16. 8
      neutron/agent/linux/external_process.py
  17. 63
      neutron/agent/linux/interface.py
  18. 5
      neutron/agent/linux/ip_lib.py
  19. 34
      neutron/agent/linux/iptables_comments.py
  20. 59
      neutron/agent/linux/iptables_firewall.py
  21. 32
      neutron/agent/linux/iptables_manager.py
  22. 46
      neutron/agent/linux/ovs_lib.py
  23. 31
      neutron/agent/linux/utils.py
  24. 13
      neutron/agent/metadata/__init__.py
  25. 22
      neutron/agent/metadata/agent.py
  26. 2
      neutron/agent/metadata/namespace_proxy.py
  27. 41
      neutron/agent/securitygroups_rpc.py
  28. 8
      neutron/api/rpc/handlers/dhcp_rpc.py
  29. 5
      neutron/api/rpc/handlers/dvr_rpc.py
  30. 4
      neutron/api/v2/attributes.py
  31. 4
      neutron/api/v2/base.py
  32. 14
      neutron/cmd/__init__.py
  33. 6
      neutron/cmd/sanity_check.py
  34. 2
      neutron/common/config.py
  35. 10
      neutron/common/constants.py
  36. 4
      neutron/common/exceptions.py
  37. 84
      neutron/db/db_base_plugin_v2.py
  38. 14
      neutron/db/firewall/__init__.py
  39. 79
      neutron/db/firewall/firewall_db.py
  40. 34
      neutron/db/l3_agentschedulers_db.py
  41. 187
      neutron/db/l3_db.py
  42. 125
      neutron/db/l3_dvr_db.py
  43. 14
      neutron/db/l3_dvrscheduler_db.py
  44. 8
      neutron/db/l3_gwmode_db.py
  45. 21
      neutron/db/l3_hamode_db.py
  46. 13
      neutron/db/loadbalancer/__init__.py
  47. 13
      neutron/db/metering/__init__.py
  48. 4
      neutron/db/metering/metering_db.py
  49. 1
      neutron/db/migration/alembic_migrations/env.py
  50. 40
      neutron/db/migration/alembic_migrations/versions/1f71e54a85e7_ml2_net_seg_model.py
  51. 107
      neutron/db/migration/alembic_migrations/versions/31d7f831a591_add_constraint_for_routerid.py
  52. 12
      neutron/db/migration/alembic_migrations/versions/3927f7f7c456_l3_extension_distributed_mode.py
  53. 61
      neutron/db/migration/alembic_migrations/versions/44621190bc02_add_uniqueconstraint_ipavailability_ranges.py
  54. 65
      neutron/db/migration/alembic_migrations/versions/544673ac99ab_add_router_port_table.py
  55. 7
      neutron/db/migration/alembic_migrations/versions/884573acbf1c_unify_nsx_router_extra_attributes.py
  56. 2
      neutron/db/migration/alembic_migrations/versions/HEAD
  57. 36
      neutron/db/migration/alembic_migrations/versions/juno_release.py
  58. 12
      neutron/db/migration/cli.py
  59. 44
      neutron/db/migration/migrate_to_ml2.py
  60. 13
      neutron/db/models_v2.py
  61. 13
      neutron/db/securitygroups_db.py
  62. 56
      neutron/db/securitygroups_rpc_base.py
  63. 14
      neutron/db/vpn/__init__.py
  64. 13
      neutron/db/vpn/vpn_db.py
  65. 14
      neutron/debug/__init__.py
  66. 25
      neutron/extensions/firewall.py
  67. 16
      neutron/extensions/l3.py
  68. 8
      neutron/extensions/l3_ext_gw_mode.py
  69. 2
      neutron/extensions/l3_ext_ha_mode.py
  70. 5
      neutron/extensions/quotasv2.py
  71. 4
      neutron/extensions/vpnaas.py
  72. 12
      neutron/hacking/checks.py
  73. 263
      neutron/locale/de/LC_MESSAGES/neutron-log-error.po
  74. 185
      neutron/locale/de/LC_MESSAGES/neutron-log-info.po
  75. 156
      neutron/locale/de/LC_MESSAGES/neutron-log-warning.po
  76. 263
      neutron/locale/en_AU/LC_MESSAGES/neutron-log-error.po
  77. 173
      neutron/locale/en_AU/LC_MESSAGES/neutron-log-info.po
  78. 156
      neutron/locale/en_AU/LC_MESSAGES/neutron-log-warning.po
  79. 20
      neutron/locale/en_GB/LC_MESSAGES/neutron-log-critical.po
  80. 268
      neutron/locale/en_GB/LC_MESSAGES/neutron-log-error.po
  81. 173
      neutron/locale/en_GB/LC_MESSAGES/neutron-log-info.po
  82. 159
      neutron/locale/en_GB/LC_MESSAGES/neutron-log-warning.po
  83. 16682
      neutron/locale/en_US/LC_MESSAGES/neutron.po
  84. 263
      neutron/locale/es/LC_MESSAGES/neutron-log-error.po
  85. 189
      neutron/locale/es/LC_MESSAGES/neutron-log-info.po
  86. 156
      neutron/locale/es/LC_MESSAGES/neutron-log-warning.po
  87. 23
      neutron/locale/fr/LC_MESSAGES/neutron-log-critical.po
  88. 263
      neutron/locale/fr/LC_MESSAGES/neutron-log-error.po
  89. 205
      neutron/locale/fr/LC_MESSAGES/neutron-log-info.po
  90. 156
      neutron/locale/fr/LC_MESSAGES/neutron-log-warning.po
  91. 264
      neutron/locale/it/LC_MESSAGES/neutron-log-error.po
  92. 187
      neutron/locale/it/LC_MESSAGES/neutron-log-info.po
  93. 156
      neutron/locale/it/LC_MESSAGES/neutron-log-warning.po
  94. 263
      neutron/locale/ja/LC_MESSAGES/neutron-log-error.po
  95. 191
      neutron/locale/ja/LC_MESSAGES/neutron-log-info.po
  96. 156
      neutron/locale/ja/LC_MESSAGES/neutron-log-warning.po
  97. 263
      neutron/locale/ko_KR/LC_MESSAGES/neutron-log-error.po
  98. 193
      neutron/locale/ko_KR/LC_MESSAGES/neutron-log-info.po
  99. 156
      neutron/locale/ko_KR/LC_MESSAGES/neutron-log-warning.po
  100. 150
      neutron/locale/neutron-log-error.pot
  101. Some files were not shown because too many files have changed in this diff Show More

124
.pylintrc

@ -2,17 +2,97 @@
[MASTER]
# Add <file or directory> to the black list. It should be a base name, not a
# path. You may set this option multiple times.
ignore=test
#
# Note the 'openstack' below is intended to match only
# neutron.openstack.common. If we ever have another 'openstack'
# dirname, then we'll need to expand the ignore features in pylint :/
ignore=.git,tests,openstack
[Messages Control]
# NOTE(justinsb): We might want to have a 2nd strict pylintrc in future
# C0111: Don't require docstrings on every method
# W0511: TODOs in code comments are fine.
# W0142: *args and **kwargs are fine.
# W0622: Redefining id is fine.
disable=C0111,W0511,W0142,W0622
[MESSAGES CONTROL]
# NOTE(gus): This is a long list. A number of these are important and
# should be re-enabled once the offending code is fixed (or marked
# with a local disable)
disable=
# "F" Fatal errors that prevent further processing
import-error,
# "I" Informational noise
locally-disabled,
# "E" Error for important programming issues (likely bugs)
access-member-before-definition,
assignment-from-no-return,
bad-except-order,
bad-super-call,
maybe-no-member,
no-member,
no-method-argument,
no-name-in-module,
no-self-argument,
not-callable,
no-value-for-parameter,
super-on-old-class,
too-few-format-args,
# "W" Warnings for stylistic problems or minor programming issues
abstract-method,
anomalous-backslash-in-string,
anomalous-unicode-escape-in-string,
arguments-differ,
attribute-defined-outside-init,
bad-builtin,
bad-indentation,
broad-except,
dangerous-default-value,
deprecated-lambda,
duplicate-key,
expression-not-assigned,
fixme,
global-statement,
global-variable-not-assigned,
logging-not-lazy,
lost-exception,
no-init,
non-parent-init-called,
pointless-string-statement,
protected-access,
redefined-builtin,
redefined-outer-name,
redefine-in-handler,
signature-differs,
star-args,
super-init-not-called,
undefined-loop-variable,
unnecessary-lambda,
unnecessary-pass,
unpacking-non-sequence,
unreachable,
unused-argument,
unused-import,
unused-variable,
useless-else-on-loop,
# "C" Coding convention violations
bad-continuation,
invalid-name,
missing-docstring,
old-style-class,
superfluous-parens,
# "R" Refactor recommendations
abstract-class-little-used,
abstract-class-not-used,
cyclic-import,
duplicate-code,
interface-not-implemented,
no-self-use,
too-few-public-methods,
too-many-ancestors,
too-many-arguments,
too-many-branches,
too-many-instance-attributes,
too-many-lines,
too-many-locals,
too-many-public-methods,
too-many-return-statements,
too-many-statements
[Basic]
[BASIC]
# Variable names can be 1 to 31 characters long, with lowercase and underscores
variable-rgx=[a-z_][a-z0-9_]{0,30}$
@ -21,7 +101,7 @@ argument-rgx=[a-z_][a-z0-9_]{1,30}$
# Method names should be at least 3 characters long
# and be lowecased with underscores
method-rgx=([a-z_][a-z0-9_]{2,50}|setUp|tearDown)$
method-rgx=([a-z_][a-z0-9_]{2,}|setUp|tearDown)$
# Module names matching neutron-* are ok (files in bin/)
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+)|(neutron-[a-z0-9_-]+))$
@ -29,14 +109,26 @@ module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+)|(neutron-[a-z0-9_-]+))$
# Don't require docstrings on tests.
no-docstring-rgx=((__.*__)|([tT]est.*)|setUp|tearDown)$
[Design]
max-public-methods=100
min-public-methods=0
max-args=6
[Variables]
[FORMAT]
# Maximum number of characters on a single line.
max-line-length=79
[VARIABLES]
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
# _ is used by our localization
additional-builtins=_
[CLASSES]
# List of interface methods to ignore, separated by a comma.
ignore-iface-methods=
[IMPORTS]
# Deprecated modules which should not be used, separated by a comma
deprecated-modules=
# should use openstack.common.jsonutils
json
[REPORTS]
# Tells whether to display a full report or only the messages
reports=no

1
HACKING.rst

@ -12,6 +12,7 @@ Neutron Specific Commandments
- [N321] Validate that jsonutils module is used instead of json
- [N322] We do not use @authors tags in source files. We have git to track
authorship.
- [N323] assert_called_once() is not a valid method
Creating Unit Tests
-------------------

9
doc/source/devref/db_layer.rst

@ -1,2 +1,11 @@
Neutron Database Layer
======================
Testing database and models sync
--------------------------------
.. automodule:: neutron.tests.unit.db.test_migration
.. autoclass:: _TestModelsMigrations
:members:

9
etc/neutron.conf

@ -251,6 +251,11 @@ lock_path = $state_path/lock
# The uuid of the admin nova tenant
# nova_admin_tenant_id =
# The name of the admin nova tenant. If the uuid of the admin nova tenant
# is set, this is optional. Useful for cases where the uuid of the admin
# nova tenant is not available when configuration is being done.
# nova_admin_tenant_name =
# Password for connection to nova in admin context.
# nova_admin_password =
@ -555,6 +560,10 @@ lock_path = $state_path/lock
# Change to "sudo" to skip the filtering and just run the comand directly
# root_helper = sudo
# Set to true to add comments to generated iptables rules that describe
# each rule's purpose. (System must support the iptables comments module.)
# comment_iptables_rules = True
# =========== items for agent management extension =============
# seconds between nodes reporting state to server; should be less than
# agent_down_time, best if it is half or less than agent_down_time

15
etc/neutron/plugins/cisco/cisco_cfg_agent.ini

@ -0,0 +1,15 @@
[cfg_agent]
# (IntOpt) Interval in seconds for processing of service updates.
# That is when the config agent's process_services() loop executes
# and it lets each service helper to process its service resources.
# rpc_loop_interval = 10
# (StrOpt) Period-separated module path to the routing service helper class.
# routing_svc_helper_class = neutron.plugins.cisco.cfg_agent.service_helpers.routing_svc_helper.RoutingServiceHelper
# (IntOpt) Timeout value in seconds for connecting to a hosting device.
# device_connection_timeout = 30
# (IntOpt) The time in seconds until a backlogged hosting device is
# presumed dead or booted to an error state.
# hosting_device_dead_timeout = 300

63
etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini

@ -1,52 +1,13 @@
[ovs]
# (StrOpt) Type of network to allocate for tenant networks. The
# default value 'local' is useful only for single-box testing and
# provides no connectivity between hosts. You MUST either change this
# to 'vlan' and configure network_vlan_ranges below or change this to
# 'gre' or 'vxlan' and configure tunnel_id_ranges below in order for
# tenant networks to provide connectivity between hosts. Set to 'none'
# to disable creation of tenant networks.
#
# tenant_network_type = local
# Example: tenant_network_type = gre
# Example: tenant_network_type = vxlan
# (ListOpt) Comma-separated list of
# <physical_network>[:<vlan_min>:<vlan_max>] tuples enumerating ranges
# of VLAN IDs on named physical networks that are available for
# allocation. All physical networks listed are available for flat and
# VLAN provider network creation. Specified ranges of VLAN IDs are
# available for tenant network allocation if tenant_network_type is
# 'vlan'. If empty, only gre, vxlan and local networks may be created.
#
# network_vlan_ranges =
# Example: network_vlan_ranges = physnet1:1000:2999
# (BoolOpt) Set to True in the server and the agents to enable support
# for GRE or VXLAN networks. Requires kernel support for OVS patch ports and
# GRE or VXLAN tunneling.
#
# WARNING: This option will be deprecated in the Icehouse release, at which
# point setting tunnel_type below will be required to enable
# tunneling.
# point setting tunnel_types will be required to enable tunneling.
#
# enable_tunneling = False
# (StrOpt) The type of tunnel network, if any, supported by the plugin. If
# this is set, it will cause tunneling to be enabled. If this is not set and
# the option enable_tunneling is set, this will default to 'gre'.
#
# tunnel_type =
# Example: tunnel_type = gre
# Example: tunnel_type = vxlan
# (ListOpt) Comma-separated list of <tun_min>:<tun_max> tuples
# enumerating ranges of GRE or VXLAN tunnel IDs that are available for
# tenant network allocation if tenant_network_type is 'gre' or 'vxlan'.
#
# tunnel_id_ranges =
# Example: tunnel_id_ranges = 1:1000
# Do not change this parameter unless you have a good reason to.
# This is the name of the OVS integration bridge. There is one per hypervisor.
# The integration bridge acts as a virtual "patch bay". All VM VIFs are
@ -55,7 +16,7 @@
#
# integration_bridge = br-int
# Only used for the agent if tunnel_id_ranges (above) is not empty for
# Only used for the agent if tunnel_id_ranges is not empty for
# the server. In most cases, the default value should be fine.
#
# tunnel_bridge = br-tun
@ -66,7 +27,7 @@
# Peer patch port in tunnel bridge for integration bridge
# tun_peer_patch_port = patch-int
# Uncomment this line for the agent if tunnel_id_ranges (above) is not
# Uncomment this line for the agent if tunnel_id_ranges is not
# empty for the server. Set local-ip to be the local IP address of
# this hypervisor.
#
@ -77,8 +38,8 @@
# bridge names to be used for flat and VLAN networks. The length of
# bridge names should be no more than 11. Each bridge must
# exist, and should have a physical network interface configured as a
# port. All physical networks listed in network_vlan_ranges on the
# server should have mappings to appropriate bridges on each agent.
# port. All physical networks configured on the server should have
# mappings to appropriate bridges on each agent.
#
# bridge_mappings =
# Example: bridge_mappings = physnet1:br-eth1
@ -102,10 +63,8 @@
# (ListOpt) The types of tenant network tunnels supported by the agent.
# Setting this will enable tunneling support in the agent. This can be set to
# either 'gre' or 'vxlan'. If this is unset, it will default to [] and
# disable tunneling support in the agent. When running the agent with the OVS
# plugin, this value must be the same as "tunnel_type" in the "[ovs]" section.
# When running the agent with ML2, you can specify as many values here as
# your compute hosts supports.
# disable tunneling support in the agent.
# You can specify as many values here as your compute hosts supports.
#
# tunnel_types =
# Example: tunnel_types = gre
@ -164,25 +123,17 @@
#
# 1. With VLANs on eth1.
# [ovs]
# network_vlan_ranges = default:2000:3999
# tunnel_id_ranges =
# integration_bridge = br-int
# bridge_mappings = default:br-eth1
#
# 2. With GRE tunneling.
# [ovs]
# network_vlan_ranges =
# tunnel_id_ranges = 1:1000
# integration_bridge = br-int
# tunnel_bridge = br-tun
# local_ip = 10.0.0.3
#
# 3. With VXLAN tunneling.
# [ovs]
# network_vlan_ranges =
# tenant_network_type = vxlan
# tunnel_type = vxlan
# tunnel_id_ranges = 1:1000
# integration_bridge = br-int
# tunnel_bridge = br-tun
# local_ip = 10.0.0.3

3
etc/neutron/rootwrap.d/l3.filters

@ -46,3 +46,6 @@ ip6tables-restore: CommandFilter, ip6tables-restore, root
# Keepalived
keepalived: CommandFilter, keepalived, root
kill_keepalived: KillFilter, root, /usr/sbin/keepalived, -HUP, -15, -9
# l3 agent to delete floatingip's conntrack state
conntrack: CommandFilter, conntrack, root

14
neutron/agent/__init__.py

@ -1,14 +0,0 @@
# Copyright 2012 OpenStack Foundation
# 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.

14
neutron/agent/common/__init__.py

@ -1,14 +0,0 @@
# Copyright 2012 OpenStack Foundation
# 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.

9
neutron/agent/common/config.py

@ -46,6 +46,11 @@ USE_NAMESPACES_OPTS = [
help=_("Allow overlapping IP.")),
]
IPTABLES_OPTS = [
cfg.BoolOpt('comment_iptables_rules', default=True,
help=_("Add comments to iptables rules.")),
]
def get_log_args(conf, log_file_name):
cmd_args = []
@ -92,6 +97,10 @@ def register_use_namespaces_opts_helper(conf):
conf.register_opts(USE_NAMESPACES_OPTS)
def register_iptables_opts(conf):
conf.register_opts(IPTABLES_OPTS, 'AGENT')
def get_root_helper(conf):
root_helper = conf.AGENT.root_helper
if root_helper != 'sudo':

14
neutron/agent/firewall.py

@ -105,6 +105,14 @@ class FirewallDriver(object):
finally:
self.filter_defer_apply_off()
def update_security_group_members(self, sg_id, ips):
"""Update group members in a security group."""
raise NotImplementedError()
def update_security_group_rules(self, sg_id, rules):
"""Update rules in a security group."""
raise NotImplementedError()
class NoopFirewallDriver(FirewallDriver):
"""Noop Firewall Driver.
@ -134,3 +142,9 @@ class NoopFirewallDriver(FirewallDriver):
@property
def ports(self):
return {}
def update_security_group_members(self, sg_id, ips):
pass
def update_security_group_rules(self, sg_id, rules):
pass

4
neutron/agent/l2population_rpc.py

@ -242,12 +242,12 @@ class L2populationRpcCallBackTunnelMixin(L2populationRpcCallBackMixin):
if agent_ip == local_ip:
continue
after = state.get('after')
after = state.get('after', [])
for mac, ip in after:
self.setup_entry_for_arp_reply(br, 'add', lvm.vlan, mac,
ip)
before = state.get('before')
before = state.get('before', [])
for mac, ip in before:
self.setup_entry_for_arp_reply(br, 'remove', lvm.vlan, mac,
ip)

212
neutron/agent/l3_agent.py

@ -22,6 +22,7 @@ eventlet.monkey_patch()
import netaddr
import os
from oslo.config import cfg
from oslo import messaging
import Queue
from neutron.agent.common import config
@ -34,13 +35,15 @@ from neutron.agent.linux import ra
from neutron.agent import rpc as agent_rpc
from neutron.common import config as common_config
from neutron.common import constants as l3_constants
from neutron.common import exceptions as n_exc
from neutron.common import ipv6_utils
from neutron.common import rpc as n_rpc
from neutron.common import topics
from neutron.common import utils as common_utils
from neutron import context
from neutron import context as n_context
from neutron import manager
from neutron.openstack.common import excutils
from neutron.openstack.common.gettextutils import _LE, _LW
from neutron.openstack.common import importutils
from neutron.openstack.common import log as logging
from neutron.openstack.common import loopingcall
@ -241,7 +244,7 @@ class LinkLocalAllocator(object):
class RouterInfo(l3_ha_agent.RouterMixin):
def __init__(self, router_id, root_helper, use_namespaces, router,
use_ipv6=False):
use_ipv6=False, ns_name=None):
self.router_id = router_id
self.ex_gw_port = None
self._snat_enabled = None
@ -254,7 +257,7 @@ class RouterInfo(l3_ha_agent.RouterMixin):
self.use_namespaces = use_namespaces
# Invoke the setter for establishing initial SNAT action
self.router = router
self.ns_name = NS_PREFIX + router_id if use_namespaces else None
self.ns_name = ns_name
self.iptables_manager = iptables_manager.IptablesManager(
root_helper=root_helper,
use_ipv6=use_ipv6,
@ -518,31 +521,47 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
LOG.error(msg)
raise SystemExit(1)
self.context = context.get_admin_context_without_session()
self.context = n_context.get_admin_context_without_session()
self.plugin_rpc = L3PluginApi(topics.L3PLUGIN, host)
self.fullsync = True
self.updated_routers = set()
self.removed_routers = set()
self.sync_progress = False
# Get the list of service plugins from Neutron Server
try:
self.neutron_service_plugins = (
self.plugin_rpc.get_service_plugin_list(self.context))
except n_rpc.RemoteError as e:
LOG.warning(_('l3-agent cannot check service plugins '
'enabled at the neutron server when startup '
'due to RPC error. It happens when the server '
'does not support this RPC API. If the error '
'is UnsupportedVersion you can ignore '
'this warning. Detail message: %s'), e)
self.neutron_service_plugins = None
# This is the first place where we contact neutron-server on startup
# so retry in case its not ready to respond.
retry_count = 5
while True:
retry_count = retry_count - 1
try:
self.neutron_service_plugins = (
self.plugin_rpc.get_service_plugin_list(self.context))
except n_rpc.RemoteError as e:
with excutils.save_and_reraise_exception() as ctx:
ctx.reraise = False
LOG.warning(_LW('l3-agent cannot check service plugins '
'enabled at the neutron server when '
'startup due to RPC error. It happens '
'when the server does not support this '
'RPC API. If the error is '
'UnsupportedVersion you can ignore this '
'warning. Detail message: %s'), e)
self.neutron_service_plugins = None
except messaging.MessagingTimeout as e:
with excutils.save_and_reraise_exception() as ctx:
if retry_count > 0:
ctx.reraise = False
LOG.warning(_LW('l3-agent cannot check service '
'plugins enabled on the neutron '
'server. Retrying. '
'Detail message: %s'), e)
continue
break
self._clean_stale_namespaces = self.conf.use_namespaces
# dvr data
self.agent_gateway_port = None
self.agent_fip_count = 0
self.fip_ns_subscribers = set()
self.local_subnets = LinkLocalAllocator(
os.path.join(self.conf.state_path, 'fip-linklocal-networks'),
FIP_LL_SUBNET)
@ -554,6 +573,15 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
self.target_ex_net_id = None
self.use_ipv6 = ipv6_utils.is_enabled()
def _fip_ns_subscribe(self, router_id):
is_first = (len(self.fip_ns_subscribers) == 0)
self.fip_ns_subscribers.add(router_id)
return is_first
def _fip_ns_unsubscribe(self, router_id):
self.fip_ns_subscribers.discard(router_id)
return len(self.fip_ns_subscribers) == 0
def _check_config_params(self):
"""Check items in configuration files.
@ -588,16 +616,22 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
'for namespace cleanup.'))
return set()
def _get_routers_namespaces(self, router_ids):
namespaces = set(self.get_ns_name(rid) for rid in router_ids)
namespaces.update(self.get_snat_ns_name(rid) for rid in router_ids)
return namespaces
def _cleanup_namespaces(self, router_namespaces, router_ids):
"""Destroy stale router namespaces on host when L3 agent restarts
This routine is called when self._clean_stale_namespaces is True.
This routine is called when self._clean_stale_namespaces is True.
The argument router_namespaces is the list of all routers namespaces
The argument router_ids is the list of ids for known routers.
"""
ns_to_ignore = set(NS_PREFIX + id for id in router_ids)
ns_to_ignore.update(SNAT_NS_PREFIX + id for id in router_ids)
# Don't destroy namespaces of routers this agent handles.
ns_to_ignore = self._get_routers_namespaces(router_ids)
ns_to_destroy = router_namespaces - ns_to_ignore
self._destroy_stale_router_namespaces(ns_to_destroy)
@ -610,7 +644,6 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
one attempt will be made to delete them.
"""
for ns in router_namespaces:
ra.disable_ipv6_ra(ns[len(NS_PREFIX):], ns, self.root_helper)
try:
self._destroy_namespace(ns)
except RuntimeError:
@ -620,8 +653,6 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
def _destroy_namespace(self, ns):
if ns.startswith(NS_PREFIX):
if self.conf.enable_metadata_proxy:
self._destroy_metadata_proxy(ns[len(NS_PREFIX):], ns)
self._destroy_router_namespace(ns)
elif ns.startswith(FIP_NS_PREFIX):
self._destroy_fip_namespace(ns)
@ -670,6 +701,10 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
self.agent_gateway_port = None
def _destroy_router_namespace(self, ns):
router_id = ns[len(NS_PREFIX):]
ra.disable_ipv6_ra(router_id, ns, self.root_helper)
if self.conf.enable_metadata_proxy:
self._destroy_metadata_proxy(router_id, ns)
ns_ip = ip_lib.IPWrapper(self.root_helper, namespace=ns)
for d in ns_ip.get_devices(exclude_loopback=True):
if d.name.startswith(INTERNAL_DEV_PREFIX):
@ -727,9 +762,14 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
raise Exception(msg)
def _router_added(self, router_id, router):
ri = RouterInfo(router_id, self.root_helper,
self.conf.use_namespaces, router,
use_ipv6=self.use_ipv6)
ns_name = (self.get_ns_name(router_id)
if self.conf.use_namespaces else None)
ri = RouterInfo(router_id=router_id,
root_helper=self.root_helper,
use_namespaces=self.conf.use_namespaces,
router=router,
use_ipv6=self.use_ipv6,
ns_name=ns_name)
self.router_info[router_id] = ri
if self.conf.use_namespaces:
self._create_router_namespace(ri)
@ -768,15 +808,13 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
for c, r in self.metadata_nat_rules():
ri.iptables_manager.ipv4['nat'].remove_rule(c, r)
ri.iptables_manager.apply()
if self.conf.enable_metadata_proxy:
self._destroy_metadata_proxy(ri.router_id, ri.ns_name)
del self.router_info[router_id]
self._destroy_router_namespace(ri.ns_name)
def _get_metadata_proxy_callback(self, router_id):
def callback(pid_file):
metadata_proxy_socket = cfg.CONF.metadata_proxy_socket
metadata_proxy_socket = self.conf.metadata_proxy_socket
proxy_cmd = ['neutron-ns-metadata-proxy',
'--pid_file=%s' % pid_file,
'--metadata_proxy_socket=%s' % metadata_proxy_socket,
@ -784,7 +822,7 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
'--state_path=%s' % self.conf.state_path,
'--metadata_port=%s' % self.conf.metadata_port]
proxy_cmd.extend(config.get_log_args(
cfg.CONF, 'neutron-ns-metadata-proxy-%s.log' %
self.conf, 'neutron-ns-metadata-proxy-%s.log' %
router_id))
return proxy_cmd
@ -948,7 +986,7 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
# Process SNAT/DNAT rules for floating IPs
fip_statuses = {}
try:
if ex_gw_port or ri.ex_gw_port:
if ex_gw_port:
existing_floating_ips = ri.floating_ips
self.process_router_floating_ip_nat_rules(ri)
ri.iptables_manager.defer_apply_off()
@ -962,7 +1000,7 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
for fip in ri.router.get(l3_constants.FLOATINGIP_KEY, []):
fip_statuses[fip['id']] = l3_constants.FLOATINGIP_STATUS_ERROR
if ex_gw_port or ri.ex_gw_port:
if ex_gw_port:
# Identify floating IPs which were disabled
ri.floating_ips = set(fip_statuses.keys())
for fip_id in existing_floating_ips - ri.floating_ips:
@ -1066,9 +1104,11 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
if ri.router['distributed']:
# filter out only FIPs for this host/agent
floating_ips = [i for i in floating_ips if i['host'] == self.host]
if floating_ips and self.agent_gateway_port is None:
self._create_agent_gateway_port(ri, floating_ips[0]
['floating_network_id'])
if floating_ips:
is_first = self._fip_ns_subscribe(ri.router_id)
if is_first:
self._create_agent_gateway_port(ri, floating_ips[0]
['floating_network_id'])
if self.agent_gateway_port:
if floating_ips and ri.dist_fip_count == 0:
@ -1115,6 +1155,9 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
else:
net = netaddr.IPNetwork(ip_cidr)
device.addr.delete(net.version, ip_cidr)
self.driver.delete_conntrack_state(root_helper=self.root_helper,
namespace=ri.ns_name,
ip=ip_cidr)
if ri.router['distributed']:
self.floating_ip_removed_dist(ri, ip_cidr)
@ -1215,6 +1258,9 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
def get_fip_ns_name(self, ext_net_id):
return (FIP_NS_PREFIX + ext_net_id)
def get_ns_name(self, router_id):
return (NS_PREFIX + router_id)
def get_snat_ns_name(self, router_id):
return (SNAT_NS_PREFIX + router_id)
@ -1384,7 +1430,7 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
self._snat_redirect_remove(ri, p, internal_interface)
if self.conf.agent_mode == 'dvr_snat' and (
ex_gw_port['binding:host_id'] == self.host):
ri.router['gw_port_host'] == self.host):
ns_name = self.get_snat_ns_name(ri.router['id'])
else:
# not hosting agent - no work to do
@ -1626,7 +1672,6 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
interface_name, floating_ip,
distributed=True)
# update internal structures
self.agent_fip_count = self.agent_fip_count + 1
ri.dist_fip_count = ri.dist_fip_count + 1
def floating_ip_removed_dist(self, ri, fip_cidr):
@ -1660,10 +1705,10 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
self.local_subnets.release(ri.router_id)
ri.rtr_fip_subnet = None
ns_ip.del_veth(fip_2_rtr_name)
# clean up fip-namespace if this is the last FIP
self.agent_fip_count = self.agent_fip_count - 1
if self.agent_fip_count == 0:
self._destroy_fip_namespace(fip_ns_name)
is_last = self._fip_ns_unsubscribe(ri.router_id)
# clean up fip-namespace if this is the last FIP
if is_last:
self._destroy_fip_namespace(fip_ns_name)
def floating_forward_rules(self, floating_ip, fixed_ip):
return [('PREROUTING', '-d %s -j DNAT --to %s' %
@ -1742,51 +1787,38 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
LOG.debug(_('Got router added to agent :%r'), payload)
self.routers_updated(context, payload)
def _process_routers(self, routers, all_routers=False):
pool = eventlet.GreenPool()
def _process_router_if_compatible(self, router):
if (self.conf.external_network_bridge and
not ip_lib.device_exists(self.conf.external_network_bridge)):
LOG.error(_("The external network bridge '%s' does not exist"),
self.conf.external_network_bridge)
return
# If namespaces are disabled, only process the router associated
# with the configured agent id.
if (not self.conf.use_namespaces and
router['id'] != self.conf.router_id):
raise n_exc.RouterNotCompatibleWithAgent(router_id=router['id'])
# Either ex_net_id or handle_internal_only_routers must be set
ex_net_id = (router['external_gateway_info'] or {}).get('network_id')
if not ex_net_id and not self.conf.handle_internal_only_routers:
raise n_exc.RouterNotCompatibleWithAgent(router_id=router['id'])
# If target_ex_net_id and ex_net_id are set they must be equal
target_ex_net_id = self._fetch_external_net_id()
# if routers are all the routers we have (They are from router sync on
# starting or when error occurs during running), we seek the
# routers which should be removed.
# If routers are from server side notification, we seek them
# from subset of incoming routers and ones we have now.
if all_routers:
prev_router_ids = set(self.router_info)
else:
prev_router_ids = set(self.router_info) & set(
[router['id'] for router in routers])
cur_router_ids = set()
for r in routers:
# If namespaces are disabled, only process the router associated
# with the configured agent id.
if (not self.conf.use_namespaces and
r['id'] != self.conf.router_id):
continue
ex_net_id = (r['external_gateway_info'] or {}).get('network_id')
if not ex_net_id and not self.conf.handle_internal_only_routers:
continue
if (target_ex_net_id and ex_net_id and
ex_net_id != target_ex_net_id):
# Double check that our single external_net_id has not changed
# by forcing a check by RPC.
if (ex_net_id != self._fetch_external_net_id(force=True)):
continue
cur_router_ids.add(r['id'])
if r['id'] not in self.router_info:
self._router_added(r['id'], r)
ri = self.router_info[r['id']]
ri.router = r
pool.spawn_n(self.process_router, ri)
# identify and remove routers that no longer exist
for router_id in prev_router_ids - cur_router_ids:
pool.spawn_n(self._router_removed, router_id)
pool.waitall()
if (target_ex_net_id and ex_net_id and ex_net_id != target_ex_net_id):
# Double check that our single external_net_id has not changed
# by forcing a check by RPC.
if ex_net_id != self._fetch_external_net_id(force=True):
raise n_exc.RouterNotCompatibleWithAgent(
router_id=router['id'])
if router['id'] not in self.router_info:
self._router_added(router['id'], router)
ri = self.router_info[router['id']]
ri.router = router
self.process_router(ri)
def _process_router_update(self):
for rp, update in self._queue.each_update_to_next_router():
@ -1810,7 +1842,15 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
self._router_removed(update.id)
continue
self._process_routers([router])
try:
self._process_router_if_compatible(router)
except n_exc.RouterNotCompatibleWithAgent as e:
LOG.exception(e.msg)
# Was the router previously handled by this agent?
if router['id'] in self.router_info:
LOG.error(_LE("Removing incompatible router '%s'"),
router['id'])
self._router_removed(router['id'])
LOG.debug("Finished a router update for %s", update.id)
rp.fetched_and_processed(update.timestamp)
@ -1820,12 +1860,6 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
while True:
pool.spawn_n(self._process_router_update)
def _process_router_delete(self):
current_removed_routers = list(self.removed_routers)
for router_id in current_removed_routers:
self._router_removed(router_id)
self.removed_routers.remove(router_id)
def _router_ids(self):
if not self.conf.use_namespaces:
return [self.conf.router_id]
@ -1851,8 +1885,6 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
try:
router_ids = self._router_ids()
self.updated_routers.clear()
self.removed_routers.clear()
timestamp = timeutils.utcnow()
routers = self.plugin_rpc.get_routers(
context, router_ids)
@ -1946,7 +1978,7 @@ class L3NATAgentWithStateReport(L3NATAgent):
'interface_driver': self.conf.interface_driver},
'start_flag': True,
'agent_type': l3_constants.AGENT_TYPE_L3}
report_interval = cfg.CONF.AGENT.report_interval
report_interval = self.conf.AGENT.report_interval
self.use_call = True
if report_interval:
self.heartbeat = loopingcall.FixedIntervalLoopingCall(

14
neutron/agent/linux/__init__.py

@ -1,14 +0,0 @@
# Copyright 2012 OpenStack Foundation
# 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.

3
neutron/agent/linux/dhcp.py

@ -730,7 +730,8 @@ class Dnsmasq(DhcpLocalProcess):
subnets = dict((subnet.id, subnet) for subnet in network.subnets)
for port in network.ports:
if port.device_owner != constants.DEVICE_OWNER_ROUTER_INTF:
if port.device_owner not in (constants.DEVICE_OWNER_ROUTER_INTF,
constants.DEVICE_OWNER_DVR_INTERFACE):
continue
for alloc in port.fixed_ips:
if subnets[alloc.subnet_id].gateway_ip == alloc.ip_address:

8
neutron/agent/linux/external_process.py

@ -30,14 +30,12 @@ OPTS = [
cfg.StrOpt('external_pids',
default='$state_path/external/pids',
help=_('Location to store child pid files')),
cfg.BoolOpt('check_child_processes', default=False,
help=_("Periodically check child processes")),
cfg.StrOpt('check_child_processes_action', default='respawn',
choices=['respawn', 'exit'],
help=_('Action to be executed when a child process dies')),
cfg.IntOpt('check_child_processes_interval', default=60,
cfg.IntOpt('check_child_processes_interval', default=0,
help=_('Interval between checks of child process liveness '
'(seconds)')),
'(seconds), use 0 to disable')),
]
@ -156,7 +154,7 @@ class ProcessMonitor(object):
self._process_managers = {}
if self._config.check_child_processes:
if self._config.check_child_processes_interval:
self._spawn_checking_thread()
def enable(self, uuid, cmd_callback, namespace=None, service=None,

63
neutron/agent/linux/interface.py

@ -23,8 +23,10 @@ from neutron.agent.common import config
from neutron.agent.linux import ip_lib
from neutron.agent.linux import ovs_lib
from neutron.agent.linux import utils
from neutron.common import constants as n_const
from neutron.common import exceptions
from neutron.extensions import flavor
from neutron.openstack.common.gettextutils import _LE
from neutron.openstack.common import importutils
from neutron.openstack.common import log as logging
@ -71,7 +73,7 @@ class LinuxInterfaceDriver(object):
# from linux IF_NAMESIZE
DEV_NAME_LEN = 14
DEV_NAME_PREFIX = 'tap'
DEV_NAME_PREFIX = n_const.TAP_DEVICE_PREFIX
def __init__(self, conf):
self.conf = conf
@ -110,6 +112,9 @@ class LinuxInterfaceDriver(object):
for ip_cidr, ip_version in previous.items():
if ip_cidr not in preserve_ips:
device.addr.delete(ip_version, ip_cidr)
self.delete_conntrack_state(root_helper=self.root_helper,
namespace=namespace,
ip=ip_cidr)
if gateway:
device.route.add_gateway(gateway)
@ -121,6 +126,43 @@ class LinuxInterfaceDriver(object):
for route in existing_onlink_routes - new_onlink_routes:
device.route.delete_onlink_route(route)
def delete_conntrack_state(self, root_helper, namespace, ip):
"""Delete conntrack state associated with an IP address.
This terminates any active connections through an IP. Call this soon
after removing the IP address from an interface so that new connections
cannot be created before the IP address is gone.
root_helper: root_helper to gain root access to call conntrack
namespace: the name of the namespace where the IP has been configured
ip: the IP address for which state should be removed. This can be
passed as a string with or without /NN. A netaddr.IPAddress or
netaddr.Network representing the IP address can also be passed.
"""
ip_str = str(netaddr.IPNetwork(ip).ip)
ip_wrapper = ip_lib.IPWrapper(root_helper, namespace=namespace)
# Delete conntrack state for ingress traffic
# If 0 flow entries have been deleted
# conntrack -D will return 1
try:
ip_wrapper.netns.execute(["conntrack", "-D", "-d", ip_str],
check_exit_code=True,
extra_ok_codes=[1])
except RuntimeError:
LOG.exception(_LE("Failed deleting ingress connection state of"
" floatingip %s"), ip_str)
# Delete conntrack state for egress traffic
try:
ip_wrapper.netns.execute(["conntrack", "-D", "-q", ip_str],
check_exit_code=True,
extra_ok_codes=[1])
except RuntimeError:
LOG.exception(_LE("Failed deleting egress connection state of"
" floatingip %s"), ip_str)
def check_bridge_exists(self, bridge):
if not ip_lib.device_exists(bridge):
raise exceptions.BridgeDoesNotExist(bridge=bridge)
@ -150,7 +192,7 @@ class NullDriver(LinuxInterfaceDriver):
class OVSInterfaceDriver(LinuxInterfaceDriver):
"""Driver for creating an internal interface on an OVS bridge."""
DEV_NAME_PREFIX = 'tap'
DEV_NAME_PREFIX = n_const.TAP_DEVICE_PREFIX
def __init__(self, conf):
super(OVSInterfaceDriver, self).__init__(conf)
@ -159,7 +201,8 @@ class OVSInterfaceDriver(LinuxInterfaceDriver):
def _get_tap_name(self, dev_name, prefix=None):
if self.conf.ovs_use_veth:
dev_name = dev_name.replace(prefix or self.DEV_NAME_PREFIX, 'tap')
dev_name = dev_name.replace(prefix or self.DEV_NAME_PREFIX,
n_const.TAP_DEVICE_PREFIX)
return dev_name
def _ovs_add_port(self, bridge, device_name, port_id, mac_address,
@ -254,7 +297,8 @@ class MidonetInterfaceDriver(LinuxInterfaceDriver):
self.root_helper,
namespace=namespace):
ip = ip_lib.IPWrapper(self.root_helper)
tap_name = device_name.replace(prefix or 'tap', 'tap')
tap_name = device_name.replace(prefix or n_const.TAP_DEVICE_PREFIX,
n_const.TAP_DEVICE_PREFIX)
# Create ns_dev in a namespace if one is configured.
root_dev, ns_dev = ip.add_veth(tap_name, device_name,
@ -293,14 +337,15 @@ class MidonetInterfaceDriver(LinuxInterfaceDriver):
class IVSInterfaceDriver(LinuxInterfaceDriver):
"""Driver for creating an internal interface on an IVS bridge."""
DEV_NAME_PREFIX = 'tap'
DEV_NAME_PREFIX = n_const.TAP_DEVICE_PREFIX
def __init__(self, conf):
super(IVSInterfaceDriver, self).__init__(conf)
self.DEV_NAME_PREFIX = 'ns-'
def _get_tap_name(self, dev_name, prefix=None):
dev_name = dev_name.replace(prefix or self.DEV_NAME_PREFIX, 'tap')
dev_name = dev_name.replace(prefix or self.DEV_NAME_PREFIX,
n_const.TAP_DEVICE_PREFIX)
return dev_name
def _ivs_add_port(self, device_name, port_id, mac_address):
@ -367,10 +412,8 @@ class BridgeInterfaceDriver(LinuxInterfaceDriver):
ip = ip_lib.IPWrapper(self.root_helper)
# Enable agent to define the prefix
if prefix:
tap_name = device_name.replace(prefix, 'tap')
else:
tap_name = device_name.replace(self.DEV_NAME_PREFIX, 'tap')
tap_name = device_name.replace(prefix or self.DEV_NAME_PREFIX,
n_const.TAP_DEVICE_PREFIX)
# Create ns_veth in a namespace if one is configured.
root_veth, ns_veth = ip.add_veth(tap_name, device_name,
namespace2=namespace)

5
neutron/agent/linux/ip_lib.py

@ -532,7 +532,8 @@ class IpNetnsCommand(IpCommandBase):
def delete(self, name):
self._as_root('delete', name, use_root_namespace=True)
def execute(self, cmds, addl_env={}, check_exit_code=True):
def execute(self, cmds, addl_env={}, check_exit_code=True,
extra_ok_codes=None):
ns_params = []
if self._parent.namespace:
if not self._parent.root_helper:
@ -546,7 +547,7 @@ class IpNetnsCommand(IpCommandBase):
return utils.execute(
ns_params + env_params + list(cmds),
root_helper=self._parent.root_helper,
check_exit_code=check_exit_code)
check_exit_code=check_exit_code, extra_ok_codes=extra_ok_codes)
def exists(self, name):
output = self._parent._execute('o', 'netns', ['list'])

34
neutron/agent/linux/iptables_comments.py

@ -0,0 +1,34 @@
# Copyright 2014 OpenStack Foundation
#
# 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.
"""iptables comments"""
# Do not translate these comments. These comments cannot contain a quote or
# an escape character because they will end up in a call to iptables and
# could interfere with other parameters.
SNAT_OUT = 'Perform source NAT on outgoing traffic.'
UNMATCH_DROP = 'Default drop rule for unmatched traffic.'
VM_INT_SG = 'Direct traffic from the VM interface to the security group chain.'
SG_TO_VM_SG = 'Jump to the VM specific chain.'
INPUT_TO_SG = 'Direct incoming traffic from VM to the security group chain.'
PAIR_ALLOW = 'Allow traffic from defined IP/MAC pairs.'
PAIR_DROP = 'Drop traffic without an IP/MAC allow rule.'
DHCP_CLIENT = 'Allow DHCP client traffic.'
DHCP_SPOOF = 'Prevent DHCP Spoofing by VM.'
UNMATCHED = 'Send unmatched traffic to the fallback chain.'
STATELESS_DROP = 'Drop packets that are not associated with a state.'
ALLOW_ASSOC = ('Direct packets associated with a known session to the RETURN '
'chain.')
IPV6_RA_ALLOW = 'Allow IPv6 ICMP traffic to allow RA packets.'

59
neutron/agent/linux/iptables_firewall.py

@ -18,6 +18,7 @@ from oslo.config import cfg
from neutron.agent import firewall
from neutron.agent.linux import ipset_manager
from neutron.agent.linux import iptables_comments as ic
from neutron.agent.linux import iptables_manager
from neutron.common import constants
from neutron.common import ipv6_utils
@ -40,6 +41,7 @@ LINUX_DEV_LEN = 14
IPSET_CHAIN_LEN = 20
IPSET_CHANGE_BULK_THRESHOLD = 10
IPSET_ADD_BULK_THRESHOLD = 5
comment_rule = iptables_manager.comment_rule
class IptablesFirewallDriver(firewall.FirewallDriver):
@ -146,9 +148,11 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
def _add_fallback_chain_v4v6(self):
self.iptables.ipv4['filter'].add_chain('sg-fallback')
self.iptables.ipv4['filter'].add_rule('sg-fallback', '-j DROP')
self.iptables.ipv4['filter'].add_rule('sg-fallback', '-j DROP',
comment=ic.UNMATCH_DROP)
self.iptables.ipv6['filter'].add_chain('sg-fallback')
self.iptables.ipv6['filter'].add_rule('sg-fallback', '-j DROP')
self.iptables.ipv6['filter'].add_rule('sg-fallback', '-j DROP',
comment=ic.UNMATCH_DROP)
def _add_chain_by_name_v4v6(self, chain_name):
self.iptables.ipv6['filter'].add_chain(chain_name)
@ -158,12 +162,15 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
self.iptables.ipv4['filter'].ensure_remove_chain(chain_name)
self.iptables.ipv6['filter'].ensure_remove_chain(chain_name)
def _add_rule_to_chain_v4v6(self, chain_name, ipv4_rules, ipv6_rules):
def _add_rule_to_chain_v4v6(self, chain_name, ipv4_rules, ipv6_rules,
comment=None):
for rule in ipv4_rules:
self.iptables.ipv4['filter'].add_rule(chain_name, rule)
self.iptables.ipv4['filter'].add_rule(chain_name, rule,
comment=comment)
for rule in ipv6_rules:
self.iptables.ipv6['filter'].add_rule(chain_name, rule)
self.iptables.ipv6['filter'].add_rule(chain_name, rule,
comment=comment)
def _get_device_name(self, port):
return port['device']
@ -183,17 +190,20 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
'-j $%s' % (self.IPTABLES_DIRECTION[direction],
device,
SG_CHAIN)]
self._add_rule_to_chain_v4v6('FORWARD', jump_rule, jump_rule)
self._add_rule_to_chain_v4v6('FORWARD', jump_rule, jump_rule,
comment=ic.VM_INT_SG)
# jump to the chain based on the device
jump_rule = ['-m physdev --%s %s --physdev-is-bridged '
'-j $%s' % (self.IPTABLES_DIRECTION[direction],
device,
chain_name)]
self._add_rule_to_chain_v4v6(SG_CHAIN, jump_rule, jump_rule)
self._add_rule_to_chain_v4v6(SG_CHAIN, jump_rule, jump_rule,
comment=ic.SG_TO_VM_SG)
if direction == EGRESS_DIRECTION:
self._add_rule_to_chain_v4v6('INPUT', jump_rule, jump_rule)
self._add_rule_to_chain_v4v6('INPUT', jump_rule, jump_rule,
comment=ic.INPUT_TO_SG)
def _split_sgr_by_ethertype(self, security_group_rules):
ipv4_sg_rules = []
@ -222,12 +232,12 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
# of the list after the allowed_address_pair rules.
table.add_rule(chain_name,
'-m mac --mac-source %s -j RETURN'
% mac)
% mac, comment=ic.PAIR_ALLOW)