From bd3e9c3b1e759d4296cdb9a816a63ef773ea5f63 Mon Sep 17 00:00:00 2001 From: Stephen Eilert Date: Tue, 15 Mar 2016 13:54:23 -0700 Subject: [PATCH 01/51] Removes host file contents from DHCP agent logs The change I3ad7864eeb2f959549ed356a1e34fa18804395cc addressed a performance impact by removing logging calls from inside the loop that creates the hosts file in memory. However, it also introduced the dumping of said hosts file to the logs. On deployments with a very high number of ports(>5K), this increases the load of the node substantially. The problem is worse when a high number of port updates is received in a short amount of time. There is also the administrative burden caused by the sheer amount of data being logged. If the content of the host file is required for debugging purposes, it can be found at /opt/stack/data/neutron/dhcp//host This patch is trivial and only removes the logging of the file contents. The 'building'/'done building' logging calls may still provide useful information. Change-Id: Ie176ef123c194c22dca0967a6acfb9a48c959e6c Closes-Bug: 1557640 (cherry picked from commit ed7411fa1c4d6a26cea3a8737b3c29ce6ff64363) --- neutron/agent/linux/dhcp.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/neutron/agent/linux/dhcp.py b/neutron/agent/linux/dhcp.py index e08a1265489..010e6a916a6 100644 --- a/neutron/agent/linux/dhcp.py +++ b/neutron/agent/linux/dhcp.py @@ -678,8 +678,7 @@ class Dnsmasq(DhcpLocalProcess): (port.mac_address, name, ip_address)) common_utils.replace_file(filename, buf.getvalue()) - LOG.debug('Done building host file %s with contents:\n%s', filename, - buf.getvalue()) + LOG.debug('Done building host file %s', filename) return filename def _get_client_id(self, port): From 1d51172babab64176716e723ae84f20e751a2ac3 Mon Sep 17 00:00:00 2001 From: Kevin Benton Date: Thu, 17 Mar 2016 05:19:19 -0700 Subject: [PATCH 02/51] Watch for 'new' events in ovsdb monitor for ofport This adjusts the event handling logic in the ovs interface monitor to watch for 'new' events as well because this is when ofports are assigned to the interface. Previously we were only watching for 'insert' events, which would never include the ofport so this led to every port being skipped initially by the OVS agent and then picked up on the next polling interval. Closes-Bug: #1560464 Change-Id: I46ac508a839c6db779323d5afb083f3425f96e87 (cherry picked from commit 62e88623d977d28c113a1e29458621f82d48f6e5) --- neutron/agent/linux/ovsdb_monitor.py | 8 ++++++++ .../functional/agent/linux/test_ovsdb_monitor.py | 16 ++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/neutron/agent/linux/ovsdb_monitor.py b/neutron/agent/linux/ovsdb_monitor.py index bf1edf3b19b..a830de740e3 100644 --- a/neutron/agent/linux/ovsdb_monitor.py +++ b/neutron/agent/linux/ovsdb_monitor.py @@ -26,6 +26,7 @@ LOG = logging.getLogger(__name__) OVSDB_ACTION_INITIAL = 'initial' OVSDB_ACTION_INSERT = 'insert' OVSDB_ACTION_DELETE = 'delete' +OVSDB_ACTION_NEW = 'new' class OvsdbMonitor(async_process.AsyncProcess): @@ -85,6 +86,7 @@ class SimpleInterfaceMonitor(OvsdbMonitor): def process_events(self): devices_added = [] devices_removed = [] + dev_to_ofport = {} for row in self.iter_stdout(): json = jsonutils.loads(row).get('data') for ovs_id, action, name, ofport, external_ids in json: @@ -99,8 +101,14 @@ class SimpleInterfaceMonitor(OvsdbMonitor): devices_added.append(device) elif action == OVSDB_ACTION_DELETE: devices_removed.append(device) + elif action == OVSDB_ACTION_NEW: + dev_to_ofport[name] = ofport + self.new_events['added'].extend(devices_added) self.new_events['removed'].extend(devices_removed) + # update any events with ofports received from 'new' action + for event in self.new_events['added']: + event['ofport'] = dev_to_ofport.get(event['name'], event['ofport']) def start(self, block=False, timeout=5): super(SimpleInterfaceMonitor, self).start() diff --git a/neutron/tests/functional/agent/linux/test_ovsdb_monitor.py b/neutron/tests/functional/agent/linux/test_ovsdb_monitor.py index d2e206a46d6..d83d17a598b 100644 --- a/neutron/tests/functional/agent/linux/test_ovsdb_monitor.py +++ b/neutron/tests/functional/agent/linux/test_ovsdb_monitor.py @@ -24,6 +24,7 @@ Tests in this module will be skipped unless: from oslo_config import cfg +from neutron.agent.common import ovs_lib from neutron.agent.linux import ovsdb_monitor from neutron.agent.linux import utils from neutron.tests.common import net_helpers @@ -133,3 +134,18 @@ class TestSimpleInterfaceMonitor(BaseMonitorTest): devices = self.monitor.get_events() self.assertTrue(devices.get('added'), 'Initial call should always be true') + + def test_get_events_includes_ofport(self): + utils.wait_until_true(lambda: self.monitor.has_updates) + self.monitor.get_events() # clear initial events + br = self.useFixture(net_helpers.OVSBridgeFixture()) + p1 = self.useFixture(net_helpers.OVSPortFixture(br.bridge)) + + def p1_event_has_ofport(): + if not self.monitor.has_updates: + return + for e in self.monitor.new_events['added']: + if (e['name'] == p1.port.name and + e['ofport'] != ovs_lib.UNASSIGNED_OFPORT): + return True + utils.wait_until_true(p1_event_has_ofport) From da1eee31057fb44ff758d99ac99eeb47b7caec6e Mon Sep 17 00:00:00 2001 From: Alex Oughton Date: Fri, 18 Mar 2016 11:12:10 -0500 Subject: [PATCH 03/51] Close XenAPI sessions in neutron-rootwrap-xen-dom0 Neutron with XenServer properly doesn't close XenAPI sessions. If it creates these sessions so rapidly, the XenServer host eventually exceeds its maximum allowed number of connections. This patch adds a close process for session. Closes-Bug: 1558721 Change-Id: Ida90a970c649745c492c28c41c4a151e4d940aa6 (cherry picked from commit 9d21b5ad7edbf9ac1fd9254e97f56966f25de8e6) --- bin/neutron-rootwrap-xen-dom0 | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/bin/neutron-rootwrap-xen-dom0 b/bin/neutron-rootwrap-xen-dom0 index f0a9e583a2b..829b9c1564b 100755 --- a/bin/neutron-rootwrap-xen-dom0 +++ b/bin/neutron-rootwrap-xen-dom0 @@ -113,11 +113,14 @@ def run_command(url, username, password, user_args, cmd_input): try: session = XenAPI.Session(url) session.login_with_password(username, password) - host = session.xenapi.session.get_this_host(session.handle) - result = session.xenapi.host.call_plugin( - host, 'netwrap', 'run_command', - {'cmd': json.dumps(user_args), 'cmd_input': json.dumps(cmd_input)}) - return json.loads(result) + try: + host = session.xenapi.session.get_this_host(session.handle) + result = session.xenapi.host.call_plugin( + host, 'netwrap', 'run_command', + {'cmd': json.dumps(user_args), 'cmd_input': json.dumps(cmd_input)}) + return json.loads(result) + finally: + session.xenapi.session.logout() except Exception as e: traceback.print_exc() sys.exit(RC_XENAPI_ERROR) From eb8ddb95bbb56bbdc658e15feebbf7f91d5ddf13 Mon Sep 17 00:00:00 2001 From: Oleg Bondarev Date: Tue, 16 Feb 2016 18:03:52 +0300 Subject: [PATCH 04/51] Move db query to fetch down bindings under try/except In case of intermittent DB failures router and network auto-rescheduling tasks may fail due to error on fetching down bindings from db. Need to put this queries under try/except to prevent unexpected exit. Closes-Bug: #1546110 Change-Id: Id48e899a5b3d906c6d1da4d03923bdda2681cd92 (cherry picked from commit b6ec40cbf754de9d189f843cbddfca67d4103ee3) --- neutron/db/agentschedulers_db.py | 13 +++++------ neutron/db/l3_agentschedulers_db.py | 23 +++++++++++-------- .../tests/unit/db/test_agentschedulers_db.py | 10 ++++++++ .../scheduler/test_dhcp_agent_scheduler.py | 8 +++++++ 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/neutron/db/agentschedulers_db.py b/neutron/db/agentschedulers_db.py index ec9735e1022..1f357702475 100644 --- a/neutron/db/agentschedulers_db.py +++ b/neutron/db/agentschedulers_db.py @@ -268,14 +268,13 @@ class DhcpAgentSchedulerDbMixin(dhcpagentscheduler cutoff = self.get_cutoff_time(agent_dead_limit) context = ncontext.get_admin_context() - down_bindings = ( - context.session.query(NetworkDhcpAgentBinding). - join(agents_db.Agent). - filter(agents_db.Agent.heartbeat_timestamp < cutoff, - agents_db.Agent.admin_state_up)) - dhcp_notifier = self.agent_notifiers.get(constants.AGENT_TYPE_DHCP) - try: + down_bindings = ( + context.session.query(NetworkDhcpAgentBinding). + join(agents_db.Agent). + filter(agents_db.Agent.heartbeat_timestamp < cutoff, + agents_db.Agent.admin_state_up)) + dhcp_notifier = self.agent_notifiers.get(constants.AGENT_TYPE_DHCP) dead_bindings = [b for b in self._filter_bindings(context, down_bindings)] agents = self.get_agents_db( diff --git a/neutron/db/l3_agentschedulers_db.py b/neutron/db/l3_agentschedulers_db.py index 11551f6011c..7427a71ba7b 100644 --- a/neutron/db/l3_agentschedulers_db.py +++ b/neutron/db/l3_agentschedulers_db.py @@ -97,17 +97,20 @@ class L3AgentSchedulerDbMixin(l3agentscheduler.L3AgentSchedulerPluginBase, cutoff = self.get_cutoff_time(agent_dead_limit) context = n_ctx.get_admin_context() - down_bindings = ( - context.session.query(RouterL3AgentBinding). - join(agents_db.Agent). - filter(agents_db.Agent.heartbeat_timestamp < cutoff, - agents_db.Agent.admin_state_up). - outerjoin(l3_attrs_db.RouterExtraAttributes, - l3_attrs_db.RouterExtraAttributes.router_id == - RouterL3AgentBinding.router_id). - filter(sa.or_(l3_attrs_db.RouterExtraAttributes.ha == sql.false(), - l3_attrs_db.RouterExtraAttributes.ha == sql.null()))) try: + down_bindings = ( + context.session.query(RouterL3AgentBinding). + join(agents_db.Agent). + filter(agents_db.Agent.heartbeat_timestamp < cutoff, + agents_db.Agent.admin_state_up). + outerjoin(l3_attrs_db.RouterExtraAttributes, + l3_attrs_db.RouterExtraAttributes.router_id == + RouterL3AgentBinding.router_id). + filter(sa.or_(l3_attrs_db.RouterExtraAttributes.ha == + sql.false(), + l3_attrs_db.RouterExtraAttributes.ha == + sql.null()))) + agents_back_online = set() for binding in down_bindings: if binding.l3_agent_id in agents_back_online: diff --git a/neutron/tests/unit/db/test_agentschedulers_db.py b/neutron/tests/unit/db/test_agentschedulers_db.py index a65953aed50..6c247c51e69 100644 --- a/neutron/tests/unit/db/test_agentschedulers_db.py +++ b/neutron/tests/unit/db/test_agentschedulers_db.py @@ -687,6 +687,16 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase): self._take_down_agent_and_run_reschedule(L3_HOSTA) # Value error self._take_down_agent_and_run_reschedule(L3_HOSTA) # Exception + def test_router_rescheduler_catches_exceptions_on_fetching_bindings(self): + with mock.patch('neutron.context.get_admin_context') as get_ctx: + mock_ctx = mock.Mock() + get_ctx.return_value = mock_ctx + mock_ctx.session.query.side_effect = db_exc.DBError() + plugin = manager.NeutronManager.get_service_plugins().get( + service_constants.L3_ROUTER_NAT) + # check that no exception is raised + plugin.reschedule_routers_from_down_agents() + def test_router_rescheduler_iterates_after_reschedule_failure(self): plugin = manager.NeutronManager.get_service_plugins().get( service_constants.L3_ROUTER_NAT) diff --git a/neutron/tests/unit/scheduler/test_dhcp_agent_scheduler.py b/neutron/tests/unit/scheduler/test_dhcp_agent_scheduler.py index cfce17e0653..e261a8bbf3f 100644 --- a/neutron/tests/unit/scheduler/test_dhcp_agent_scheduler.py +++ b/neutron/tests/unit/scheduler/test_dhcp_agent_scheduler.py @@ -366,6 +366,14 @@ class TestNetworksFailover(TestDhcpSchedulerBaseTestCase, # just make sure that no exception is raised self.remove_networks_from_down_agents() + def test_reschedule_network_catches_exceptions_on_fetching_bindings(self): + with mock.patch('neutron.context.get_admin_context') as get_ctx: + mock_ctx = mock.Mock() + get_ctx.return_value = mock_ctx + mock_ctx.session.query.side_effect = Exception() + # just make sure that no exception is raised + self.remove_networks_from_down_agents() + def test_reschedule_doesnt_occur_if_no_agents(self): agents = self._create_and_set_agents_down(['host-a', 'host-b'], 2) self._test_schedule_bind_network([agents[0]], self.network_id) From ef6ea62d5d1fc767a23e3caf2716e76f90d63f03 Mon Sep 17 00:00:00 2001 From: Andreas Scheuring Date: Wed, 9 Mar 2016 13:56:22 +0100 Subject: [PATCH 05/51] l3: Send notify on router_create when ext gw is specified A router that got created with an external gateway specified now triggers a notfiy_router_updated event. This triggers scheduling of the router and creation of the network namespace on the target node. Change-Id: I7f6ff5edf6a9c5ffa6d8978c1f3de0e106b6a8bb Closes-Bug: #1535707 (cherry picked from commit da00d1a186c55c91887c9546e893f6d075a2c2ad) --- neutron/db/l3_db.py | 7 +++++ neutron/tests/unit/db/test_l3_db.py | 42 +++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/neutron/db/l3_db.py b/neutron/db/l3_db.py index ccfe41222ff..77b02ac13ff 100644 --- a/neutron/db/l3_db.py +++ b/neutron/db/l3_db.py @@ -1575,6 +1575,13 @@ class L3RpcNotifierMixin(object): class L3_NAT_db_mixin(L3_NAT_dbonly_mixin, L3RpcNotifierMixin): """Mixin class to add rpc notifier methods to db_base_plugin_v2.""" + def create_router(self, context, router): + router_dict = super(L3_NAT_db_mixin, self).create_router(context, + router) + if router_dict.get('external_gateway_info'): + self.notify_router_updated(context, router_dict['id'], None) + return router_dict + def update_router(self, context, id, router): router_dict = super(L3_NAT_db_mixin, self).update_router(context, id, router) diff --git a/neutron/tests/unit/db/test_l3_db.py b/neutron/tests/unit/db/test_l3_db.py index 71930362d97..dc8b3c924f9 100644 --- a/neutron/tests/unit/db/test_l3_db.py +++ b/neutron/tests/unit/db/test_l3_db.py @@ -207,3 +207,45 @@ class TestL3_NAT_dbonly_mixin(base.BaseTestCase): events.AFTER_UPDATE, mock.ANY, context=mock.ANY, subnetpool_id='fake_id') + + +class L3_NAT_db_mixin(base.BaseTestCase): + def setUp(self): + super(L3_NAT_db_mixin, self).setUp() + self.db = l3_db.L3_NAT_db_mixin() + + def _test_create_router(self, external_gateway_info=None): + router_db = l3_db.Router(id='123') + router_dict = {'id': '123', 'tenant_id': '456', + 'external_gateway_info': external_gateway_info} + # Need to use a copy here as the create_router method pops the gateway + # information + router_input = {'router': router_dict.copy()} + + with mock.patch.object(l3_db.L3_NAT_dbonly_mixin, '_create_router_db', + return_value=router_db) as crd,\ + mock.patch.object(l3_db.L3_NAT_dbonly_mixin, '_make_router_dict', + return_value=router_dict),\ + mock.patch.object(l3_db.L3_NAT_dbonly_mixin, + '_update_router_gw_info') as urgi,\ + mock.patch.object(l3_db.L3_NAT_db_mixin, 'notify_router_updated')\ + as nru: + + self.db.create_router(mock.ANY, router_input) + self.assertTrue(crd.called) + if external_gateway_info: + self.assertTrue(urgi.called) + self.assertTrue(nru.called) + else: + self.assertFalse(urgi.called) + self.assertFalse(nru.called) + + def test_create_router_no_gateway(self): + self._test_create_router() + + def test_create_router_gateway(self): + ext_gateway_info = {'network_id': 'net-id', 'enable_snat': True, + 'external_fixed_ips': [ + {'subnet_id': 'subnet-id', + 'ip_address': 'ip'}]} + self._test_create_router(ext_gateway_info) From c6ef57a6d5f0397b1abf865815bd71d40292f482 Mon Sep 17 00:00:00 2001 From: Jakub Libosvar Date: Wed, 24 Feb 2016 16:34:07 +0000 Subject: [PATCH 06/51] ovs-fw: Mark conntrack entries invalid if no rule is matched This patch makes sure that existing connection breaks once security group rule that allowed such connection is removed. Due to correctly track connections on the same hypervisor, zones were changed from per-port to per-network (based on port's vlan tag). This information is now stored in register 6. Also there was added a test for RELATED connections to avoid marking such connection as invalid by REPLY rules. Closes-Bug: 1549370 Change-Id: Ibb5942a980ddd8f2dd7ac328e9559a80c05789bb (cherry picked from commit 4f6aa3ffde2fd68b85bc5dfdaf6c2684931f3f61) --- doc/source/devref/openvswitch_firewall.rst | 250 +++++++++++++++--- .../linux/openvswitch_firewall/constants.py | 17 +- .../linux/openvswitch_firewall/firewall.py | 207 ++++++++++++--- .../agent/linux/openvswitch_firewall/rules.py | 5 +- .../openvswitch/agent/common/constants.py | 3 + .../openvswitch/agent/ovs_neutron_agent.py | 10 +- neutron/tests/common/conn_testers.py | 22 +- neutron/tests/common/machine_fixtures.py | 3 + neutron/tests/common/net_helpers.py | 15 ++ .../tests/functional/agent/test_firewall.py | 89 +++++-- .../openvswitch_firewall/test_firewall.py | 54 +++- .../linux/openvswitch_firewall/test_rules.py | 22 +- .../agent/test_ovs_neutron_agent.py | 8 +- .../openvswitch/agent/test_ovs_tunnel.py | 2 +- 14 files changed, 572 insertions(+), 135 deletions(-) diff --git a/doc/source/devref/openvswitch_firewall.rst b/doc/source/devref/openvswitch_firewall.rst index 2d49c4f11e8..2ebccd99239 100644 --- a/doc/source/devref/openvswitch_firewall.rst +++ b/doc/source/devref/openvswitch_firewall.rst @@ -30,6 +30,10 @@ Class ``SGPortMap`` was created to keep state consistent, and maps from ports to security groups and vice-versa. Every port and security group is represented by its own object encapsulating the necessary information. +Note: Open vSwitch firewall driver uses register 5 for marking flow +related to port and register 6 which defines network and is used for conntrack +zones. + Firewall API calls ------------------ @@ -86,53 +90,217 @@ then expanded into several OpenFlow rules by the method Rules example with explanation: ------------------------------- -TODO: Rules below will be awesomly explained +The following example presents two ports on the same host. They have different +security groups and there is icmp traffic allowed from first security group to +the second security group. Ports have following attributes: :: - table=0, priority=100,in_port=2 actions=load:0x2->NXM_NX_REG5[],resubmit(,71) - table=0, priority=100,in_port=1 actions=load:0x1->NXM_NX_REG5[],resubmit(,71) - table=0, priority=90,dl_dst=fa:16:3e:9b:67:b2 actions=load:0x2->NXM_NX_REG5[],resubmit(,81) - table=0, priority=90,dl_dst=fa:16:3e:44:de:7a actions=load:0x1->NXM_NX_REG5[],resubmit(,81) - table=0, priority=0 actions=NORMAL - table=0, priority=1 actions=NORMAL - table=71, priority=95,arp,in_port=2,dl_src=fa:16:3e:9b:67:b2,arp_spa=192.168.0.2 actions=NORMAL - table=71, priority=95,arp,in_port=1,dl_src=fa:16:3e:44:de:7a,arp_spa=192.168.0.1 actions=NORMAL - table=71, priority=90,ct_state=-trk,in_port=2,dl_src=fa:16:3e:9b:67:b2 actions=ct(table=72,zone=NXM_NX_REG5[0..15]) - table=71, priority=90,ct_state=-trk,in_port=1,dl_src=fa:16:3e:44:de:7a actions=ct(table=72,zone=NXM_NX_REG5[0..15]) - table=71, priority=70,udp,in_port=2,tp_src=68,tp_dst=67 actions=NORMAL - table=71, priority=70,udp6,in_port=2,tp_src=546,tp_dst=547 actions=NORMAL - table=71, priority=60,udp,in_port=2,tp_src=67,tp_dst=68 actions=drop - table=71, priority=60,udp6,in_port=2,tp_src=547,tp_dst=546 actions=drop - table=71, priority=70,udp,in_port=1,tp_src=68,tp_dst=67 actions=NORMAL - table=71, priority=70,udp6,in_port=1,tp_src=546,tp_dst=547 actions=NORMAL - table=71, priority=60,udp,in_port=1,tp_src=67,tp_dst=68 actions=drop - table=71, priority=60,udp6,in_port=1,tp_src=547,tp_dst=546 actions=drop - table=71, priority=10,ct_state=-trk,in_port=2 actions=drop - table=71, priority=10,ct_state=-trk,in_port=1 actions=drop + Port 1 + - plugged to the port 1 in OVS bridge + - ip address: 192.168.0.1 + - mac address: fa:16:3e:a4:22:10 + - security group 1: can send icmp packets out + + Port 2 + - plugged to the port 2 in OVS bridge + - ip address: 192.168.0.2 + - mac address: fa:16:3e:24:57:c7 + - security group 2: can receive icmp packets from security group 1 + +The first ``table 0`` distinguishes the traffic to ingress or egress and loads +to ``register 5`` value identifying port traffic. +Ingress flow is determined by switch port number and egress flow is determined +by destination mac address. ``register 6`` contains + +:: + + table=0, priority=100,in_port=1 actions=load:0x1->NXM_NX_REG5[],load:0x284->NXM_NX_REG6[],resubmit(,71) + table=0, priority=100,in_port=2 actions=load:0x2->NXM_NX_REG5[],load:0x284->NXM_NX_REG6[],resubmit(,71) + table=0, priority=90,dl_dst=fa:16:3e:a4:22:10 actions=load:0x1->NXM_NX_REG5[],load:0x284->NXM_NX_REG6[],resubmit(,81) + table=0, priority=90,dl_dst=fa:16:3e:24:57:c7 actions=load:0x2->NXM_NX_REG5[],load:0x284->NXM_NX_REG6[],resubmit(,81) + table=0, priority=0 actions=NORMAL + +:: + +Following ``table 71`` implements arp spoofing protection, ip spoofing +protection, allows traffic for obtaining ip addresses (dhcp, dhcpv6, slaac, +ndp) for egress traffic and allows arp replies. Also identifies not tracked +connections which are processed later with information obtained from +conntrack. Notice the ``zone=NXM_NX_REG6[0..15]`` in ``actions`` when obtaining +information from conntrack. It says every port has its own conntrack zone +defined by value in ``register 6``. It's there to avoid accepting established +traffic that belongs to different port with same conntrack parameters. + +Rules below allow ICMPv6 traffic for multicast listeners, neighbour +solicitation and neighbour advertisement. + +:: + + table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=130 actions=NORMAL + table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=131 actions=NORMAL + table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=132 actions=NORMAL + table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=135 actions=NORMAL + table=71, priority=95,icmp6,reg5=0x1,in_port=1,icmp_type=136 actions=NORMAL + table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=130 actions=NORMAL + table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=131 actions=NORMAL + table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=132 actions=NORMAL + table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=135 actions=NORMAL + table=71, priority=95,icmp6,reg5=0x2,in_port=2,icmp_type=136 actions=NORMAL + +Following rules implement arp spoofing protection + +:: + + table=71, priority=95,arp,reg5=0x1,in_port=1,dl_src=fa:16:3e:a4:22:10,arp_spa=192.168.0.1 actions=NORMAL + table=71, priority=95,arp,reg5=0x2,in_port=2,dl_src=fa:16:3e:24:57:c7,arp_spa=192.168.0.2 actions=NORMAL + +DHCP and DHCPv6 traffic is allowed to instance but DHCP servers are blocked on +instances. + +:: + + table=71, priority=80,udp,reg5=0x1,in_port=1,tp_src=68,tp_dst=67 actions=resubmit(,73) + table=71, priority=80,udp6,reg5=0x1,in_port=1,tp_src=546,tp_dst=547 actions=resubmit(,73) + table=71, priority=70,udp,reg5=0x1,in_port=1,tp_src=67,tp_dst=68 actions=drop + table=71, priority=70,udp6,reg5=0x1,in_port=1,tp_src=547,tp_dst=546 actions=drop + table=71, priority=80,udp,reg5=0x2,in_port=2,tp_src=68,tp_dst=67 actions=resubmit(,73) + table=71, priority=80,udp6,reg5=0x2,in_port=2,tp_src=546,tp_dst=547 actions=resubmit(,73) + table=71, priority=70,udp,reg5=0x2,in_port=2,tp_src=67,tp_dst=68 actions=drop + table=71, priority=70,udp6,reg5=0x2,in_port=2,tp_src=547,tp_dst=546 actions=drop + +Flowing rules obtain conntrack information for valid ip and mac address +combinations. All other packets are dropped. + +:: + + table=71, priority=65,ct_state=-trk,ip,reg5=0x1,in_port=1,dl_src=fa:16:3e:a4:22:10,nw_src=192.168.0.1 actions=ct(table=72,zone=NXM_NX_REG6[0..15]) + table=71, priority=65,ct_state=-trk,ip,reg5=0x2,in_port=2,dl_src=fa:16:3e:24:57:c7,nw_src=192.168.0.2 actions=ct(table=72,zone=NXM_NX_REG6[0..15]) + table=71, priority=65,ct_state=-trk,ipv6,reg5=0x1,in_port=1,dl_src=fa:16:3e:a4:22:10,ipv6_src=fe80::f816:3eff:fea4:2210 actions=ct(table=72,zone=NXM_NX_REG6[0..15]) + table=71, priority=65,ct_state=-trk,ipv6,reg5=0x2,in_port=2,dl_src=fa:16:3e:24:57:c7,ipv6_src=fe80::f816:3eff:fe24:57c7 actions=ct(table=72,zone=NXM_NX_REG6[0..15]) + table=71, priority=10,ct_state=-trk,reg5=0x1,in_port=1 actions=drop + table=71, priority=10,ct_state=-trk,reg5=0x2,in_port=2 actions=drop table=71, priority=0 actions=drop - table=72, priority=90,ct_state=+inv+trk actions=drop - table=72, priority=80,ct_state=+est-rel-inv+trk actions=NORMAL - table=72, priority=80,ct_state=-est+rel-inv+trk actions=NORMAL - table=72, priority=70,icmp,dl_src=fa:16:3e:44:de:7a,nw_src=192.168.0.1 actions=resubmit(,73) + + +``table 72`` accepts only established or related connections, and implements +rules defined by the security group. As this egress connection might also be an +ingress connection for some other port, it's not switched yet but eventually +processed by ingress pipeline. + +All established or new connections defined by security group rule are +``accepted``, which will be explained later. All invalid packets are dropped. +In case below we allow all icmp egress traffic. + +:: + + table=72, priority=70,ct_state=+est-rel-rpl,icmp,reg5=0x1,dl_src=fa:16:3e:a4:22:10 actions=resubmit(,73) + table=72, priority=70,ct_state=+new-est,icmp,reg5=0x1,dl_src=fa:16:3e:a4:22:10 actions=resubmit(,73) + table=72, priority=50,ct_state=+inv+trk actions=drop + + +Important on the flows below is the ``ct_mark=0x1``. Such value have flows that +were marked as not existing anymore by rule introduced later. Those are +typically connections that were allowed by some security group rule and the +rule was removed. + +:: + + table=72, priority=50,ct_mark=0x1,reg5=0x1 actions=drop + table=72, priority=50,ct_mark=0x1,reg5=0x2 actions=drop + +All other connections that are not marked and are established or related are +allowed. + +:: + + table=72, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x1 actions=NORMAL + table=72, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x2 actions=NORMAL + table=72, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x1 actions=NORMAL + table=72, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x2 actions=NORMAL + +In the following flows are marked established connections that weren't matched +in the previous flows, which means they don't have accepting security group +rule anymore. + +:: + + table=72, priority=40,ct_state=-est,reg5=0x1 actions=drop + table=72, priority=40,ct_state=+est,reg5=0x1 actions=ct(commit,zone=NXM_NX_REG6[0..15],exec(load:0x1->NXM_NX_CT_MARK[])) + table=72, priority=40,ct_state=-est,reg5=0x2 actions=drop + table=72, priority=40,ct_state=+est,reg5=0x2 actions=ct(commit,zone=NXM_NX_REG6[0..15],exec(load:0x1->NXM_NX_CT_MARK[])) table=72, priority=0 actions=drop - table=73, priority=100,dl_dst=fa:16:3e:9b:67:b2 actions=resubmit(,81) - table=73, priority=100,dl_dst=fa:16:3e:44:de:7a actions=resubmit(,81) - table=73, priority=90,in_port=2 actions=ct(commit,zone=NXM_NX_REG5[0..15]) - table=73, priority=90,in_port=1 actions=ct(commit,zone=NXM_NX_REG5[0..15]) - table=81, priority=100,arp,dl_dst=fa:16:3e:9b:67:b2 actions=output:2 - table=81, priority=100,arp,dl_dst=fa:16:3e:44:de:7a actions=output:1 - table=81, priority=95,ct_state=-trk,ip actions=ct(table=82,zone=NXM_NX_REG5[0..15]) - table=81, priority=95,ct_state=-trk,ipv6 actions=ct(table=82,zone=NXM_NX_REG5[0..15]) - table=81, priority=80,dl_dst=fa:16:3e:9b:67:b2 actions=resubmit(,82) - table=81, priority=80,dl_dst=fa:16:3e:44:de:7a actions=resubmit(,82) + +In following ``table 73`` are all detected ingress connections sent to ingress +pipeline. Since the connection was already accepted by egress pipeline, all +remaining egress connections are sent to normal switching. + +:: + + table=73, priority=100,dl_dst=fa:16:3e:a4:22:10 actions=load:0x1->NXM_NX_REG5[],resubmit(,81) + table=73, priority=100,dl_dst=fa:16:3e:24:57:c7 actions=load:0x2->NXM_NX_REG5[],resubmit(,81) + table=73, priority=90,ct_state=+new-est,reg5=0x1 actions=ct(commit,zone=NXM_NX_REG6[0..15]),NORMAL + table=73, priority=90,ct_state=+new-est,reg5=0x2 actions=ct(commit,zone=NXM_NX_REG6[0..15]),NORMAL + table=73, priority=80,reg5=0x1 actions=NORMAL + table=73, priority=80,reg5=0x2 actions=NORMAL + table=73, priority=0 actions=drop + +``table 81`` is similar to ``table 71``, allows basic ingress traffic for +obtaining ip address and arp queries. Not tracked packets are sent to obtain +conntrack information. + +:: + + table=81, priority=100,arp,reg5=0x1,dl_dst=fa:16:3e:a4:22:10 actions=output:1 + table=81, priority=100,arp,reg5=0x2,dl_dst=fa:16:3e:24:57:c7 actions=output:2 + table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=130 actions=output:1 + table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=131 actions=output:1 + table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=132 actions=output:1 + table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=135 actions=output:1 + table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=136 actions=output:1 + table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=130 actions=output:2 + table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=131 actions=output:2 + table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=132 actions=output:2 + table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=135 actions=output:2 + table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=136 actions=output:2 + table=81, priority=95,udp,reg5=0x1,tp_src=67,tp_dst=68 actions=output:1 + table=81, priority=95,udp6,reg5=0x1,tp_src=547,tp_dst=546 actions=output:1 + table=81, priority=95,udp,reg5=0x2,tp_src=67,tp_dst=68 actions=output:2 + table=81, priority=95,udp6,reg5=0x2,tp_src=547,tp_dst=546 actions=output:2 + table=81, priority=90,ct_state=-trk,ip,reg5=0x1 actions=ct(table=82,zone=NXM_NX_REG6[0..15]) + table=81, priority=90,ct_state=-trk,ipv6,reg5=0x1 actions=ct(table=82,zone=NXM_NX_REG6[0..15]) + table=81, priority=90,ct_state=-trk,ip,reg5=0x2 actions=ct(table=82,zone=NXM_NX_REG6[0..15]) + table=81, priority=90,ct_state=-trk,ipv6,reg5=0x2 actions=ct(table=82,zone=NXM_NX_REG6[0..15]) + table=81, priority=80,ct_state=+trk,reg5=0x1,dl_dst=fa:16:3e:a4:22:10 actions=resubmit(,82) + table=81, priority=80,ct_state=+trk,reg5=0x2,dl_dst=fa:16:3e:24:57:c7 actions=resubmit(,82) table=81, priority=0 actions=drop - table=82, priority=100,ct_state=+inv+trk actions=drop - table=82, priority=80,ct_state=+est-rel-inv+trk,dl_dst=fa:16:3e:44:de:7a actions=output:1 - table=82, priority=80,ct_state=-est+rel-inv+trk,dl_dst=fa:16:3e:44:de:7a actions=output:1 - table=82, priority=80,ct_state=+est-rel-inv+trk,dl_dst=fa:16:3e:9b:67:b2 actions=output:2 - table=82, priority=80,ct_state=-est+rel-inv+trk,dl_dst=fa:16:3e:9b:67:b2 actions=output:2 - table=82, priority=70,icmp,dl_dst=fa:16:3e:9b:67:b2,nw_src=192.168.0.1,nw_dst=192.168.0.2 actions=ct(commit,zone=NXM_NX_REG5[0..15]),output:2 + +Similarly to ``table 72``, ``table 82`` accepts established and related +connections. In this case we allow all icmp traffic coming from +``security group 1`` which is in this case only ``port 1`` with ip address +``192.168.0.1``. + +:: + + table=82, priority=70,ct_state=+est-rel-rpl,icmp,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,nw_src=192.168.0.1 actions=output:2 + table=82, priority=70,ct_state=+new-est,icmp,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,nw_src=192.168.0.1 actions=output:2,ct(commit,zone=NXM_NX_REG6[0..15]) + table=82, priority=50,ct_state=+inv+trk actions=drop + +The mechanism for dropping connections that are not allowed anymore is the +same as in ``table 72``. + +:: + + table=82, priority=50,ct_mark=0x1,reg5=0x1 actions=drop + table=82, priority=50,ct_mark=0x1,reg5=0x2 actions=drop + table=82, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x1,dl_dst=fa:16:3e:a4:22:10 actions=output:1 + table=82, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x2,dl_dst=fa:16:3e:24:57:c7 actions=output:2 + table=82, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x1,dl_dst=fa:16:3e:a4:22:10 actions=output:1 + table=82, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x2,dl_dst=fa:16:3e:24:57:c7 actions=output:2 + table=82, priority=40,ct_state=-est,reg5=0x1 actions=drop + table=82, priority=40,ct_state=+est,reg5=0x1 actions=ct(commit,zone=NXM_NX_REG6[0..15],exec(load:0x1->NXM_NX_CT_MARK[])) + table=82, priority=40,ct_state=-est,reg5=0x2 actions=drop + table=82, priority=40,ct_state=+est,reg5=0x2 actions=ct(commit,zone=NXM_NX_REG6[0..15],exec(load:0x1->NXM_NX_CT_MARK[])) table=82, priority=0 actions=drop diff --git a/neutron/agent/linux/openvswitch_firewall/constants.py b/neutron/agent/linux/openvswitch_firewall/constants.py index 347db037a5f..f34578ec455 100644 --- a/neutron/agent/linux/openvswitch_firewall/constants.py +++ b/neutron/agent/linux/openvswitch_firewall/constants.py @@ -16,9 +16,22 @@ from neutron.common import constants OF_STATE_NOT_TRACKED = "-trk" -OF_STATE_ESTABLISHED = "+trk+est-rel-inv" -OF_STATE_RELATED = "+trk+rel-est-inv" +OF_STATE_TRACKED = "+trk" +OF_STATE_NEW_NOT_ESTABLISHED = "+new-est" +OF_STATE_NOT_ESTABLISHED = "-est" +OF_STATE_ESTABLISHED = "+est" +OF_STATE_ESTABLISHED_NOT_REPLY = "+est-rel-rpl" +OF_STATE_ESTABLISHED_REPLY = "+est-rel+rpl" +OF_STATE_RELATED = "-new-est+rel-inv" OF_STATE_INVALID = "+trk+inv" +OF_STATE_NEW = "+new" +OF_STATE_NOT_REPLY_NOT_NEW = "-new-rpl" + +CT_MARK_NORMAL = '0x0' +CT_MARK_INVALID = '0x1' + +REG_PORT = 5 +REG_NET = 6 protocol_to_nw_proto = { constants.PROTO_NAME_ICMP: constants.PROTO_NUM_ICMP, diff --git a/neutron/agent/linux/openvswitch_firewall/firewall.py b/neutron/agent/linux/openvswitch_firewall/firewall.py index 03f33d21d2b..b3ff55c8ae6 100644 --- a/neutron/agent/linux/openvswitch_firewall/firewall.py +++ b/neutron/agent/linux/openvswitch_firewall/firewall.py @@ -29,6 +29,31 @@ from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants \ LOG = logging.getLogger(__name__) +def _replace_register(flow_params, register_number, register_value): + """Replace value from flows to given register number + + 'register_value' key in dictionary will be replaced by register number + given by 'register_number' + + :param flow_params: Dictionary containing defined flows + :param register_number: The number of register where value will be stored + :param register_value: Key to be replaced by register number + + """ + try: + reg_port = flow_params[register_value] + del flow_params[register_value] + flow_params['reg{:d}'.format(register_number)] = reg_port + except KeyError: + pass + + +def create_reg_numbers(flow_params): + """Replace reg_(port|net) values with defined register numbers""" + _replace_register(flow_params, ovsfw_consts.REG_PORT, 'reg_port') + _replace_register(flow_params, ovsfw_consts.REG_NET, 'reg_net') + + class OVSFWPortNotFound(exceptions.NeutronException): message = _("Port %(port_id)s is not managed by this agent. ") @@ -56,8 +81,9 @@ class SecurityGroup(object): class OFPort(object): - def __init__(self, port_dict, ovs_port): + def __init__(self, port_dict, ovs_port, vlan_tag): self.id = port_dict['device'] + self.vlan_tag = vlan_tag self.mac = ovs_port.vif_mac self.lla_address = str(ipv6_utils.get_ipv6_addr_by_EUI64( constants.IPV6_LLA_PREFIX, self.mac)) @@ -173,8 +199,18 @@ class OVSFirewallDriver(firewall.FirewallDriver): agent. This method is never called from that place. """ + def _accept_flow(self, **flow): + flow['ct_state'] = ovsfw_consts.OF_STATE_ESTABLISHED_NOT_REPLY + self._add_flow(**flow) + flow['ct_state'] = ovsfw_consts.OF_STATE_NEW_NOT_ESTABLISHED + if flow['table'] == ovs_consts.RULES_INGRESS_TABLE: + flow['actions'] += ',ct(commit,zone=NXM_NX_REG{:d}[0..15])'.format( + ovsfw_consts.REG_NET) + self._add_flow(**flow) + def _add_flow(self, **kwargs): dl_type = kwargs.get('dl_type') + create_reg_numbers(kwargs) if isinstance(dl_type, int): kwargs['dl_type'] = "0x{:04x}".format(dl_type) if self._deferred: @@ -183,6 +219,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): self.int_br.br.add_flow(**kwargs) def _delete_flows(self, **kwargs): + create_reg_numbers(kwargs) if self._deferred: self.int_br.delete_flows(**kwargs) else: @@ -205,7 +242,13 @@ class OVSFirewallDriver(firewall.FirewallDriver): ovs_port = self.int_br.br.get_vif_port_by_id(port_id) if not ovs_port: raise OVSFWPortNotFound(port_id=port_id) - of_port = OFPort(port, ovs_port) + + try: + port_vlan_id = int(self.int_br.br.db_get_val( + 'Port', ovs_port.port_name, 'tag')) + except TypeError: + port_vlan_id = ovs_consts.DEAD_VLAN_TAG + of_port = OFPort(port, ovs_port, port_vlan_id) self.sg_port_map.create_port(of_port, port) else: self.sg_port_map.update_port(of_port, port) @@ -289,8 +332,14 @@ class OVSFirewallDriver(firewall.FirewallDriver): table=ovs_consts.LOCAL_SWITCHING, priority=100, in_port=port.ofport, - actions='set_field:{:d}->reg5,resubmit(,{:d})'.format( - port.ofport, ovs_consts.BASE_EGRESS_TABLE) + actions='set_field:{:d}->reg{:d},' + 'set_field:{:d}->reg{:d},' + 'resubmit(,{:d})'.format( + port.ofport, + ovsfw_consts.REG_PORT, + port.vlan_tag, + ovsfw_consts.REG_NET, + ovs_consts.BASE_EGRESS_TABLE) ) # Identify ingress flows after egress filtering @@ -298,8 +347,14 @@ class OVSFirewallDriver(firewall.FirewallDriver): table=ovs_consts.LOCAL_SWITCHING, priority=90, dl_dst=port.mac, - actions='set_field:{:d}->reg5,resubmit(,{:d})'.format( - port.ofport, ovs_consts.BASE_INGRESS_TABLE), + actions='set_field:{:d}->reg{:d},' + 'set_field:{:d}->reg{:d},' + 'resubmit(,{:d})'.format( + port.ofport, + ovsfw_consts.REG_PORT, + port.vlan_tag, + ovsfw_consts.REG_NET, + ovs_consts.BASE_INGRESS_TABLE), ) self._initialize_egress(port) @@ -311,7 +366,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): table=ovs_consts.BASE_EGRESS_TABLE, priority=95, in_port=port.ofport, - reg5=port.ofport, + reg_port=port.ofport, dl_type=constants.ETHERTYPE_IPV6, nw_proto=constants.PROTO_NUM_IPV6_ICMP, icmp_type=icmp_type, @@ -330,7 +385,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): table=ovs_consts.BASE_EGRESS_TABLE, priority=95, in_port=port.ofport, - reg5=port.ofport, + reg_port=port.ofport, dl_src=mac_addr, dl_type=constants.ETHERTYPE_ARP, arp_spa=ip_addr, @@ -339,14 +394,15 @@ class OVSFirewallDriver(firewall.FirewallDriver): self._add_flow( table=ovs_consts.BASE_EGRESS_TABLE, priority=65, - reg5=port.ofport, + reg_port=port.ofport, ct_state=ovsfw_consts.OF_STATE_NOT_TRACKED, dl_type=constants.ETHERTYPE_IP, in_port=port.ofport, dl_src=mac_addr, nw_src=ip_addr, - actions='ct(table={:d},zone=NXM_NX_REG5[0..15])'.format( - ovs_consts.RULES_EGRESS_TABLE) + actions='ct(table={:d},zone=NXM_NX_REG{:d}[0..15])'.format( + ovs_consts.RULES_EGRESS_TABLE, + ovsfw_consts.REG_NET) ) # Apply mac/ip pairs for IPv6 @@ -356,14 +412,15 @@ class OVSFirewallDriver(firewall.FirewallDriver): self._add_flow( table=ovs_consts.BASE_EGRESS_TABLE, priority=65, - reg5=port.ofport, + reg_port=port.ofport, in_port=port.ofport, ct_state=ovsfw_consts.OF_STATE_NOT_TRACKED, dl_type=constants.ETHERTYPE_IPV6, dl_src=mac_addr, ipv6_src=ip_addr, - actions='ct(table={:d},zone=NXM_NX_REG5[0..15])'.format( - ovs_consts.RULES_EGRESS_TABLE) + actions='ct(table={:d},zone=NXM_NX_REG{:d}[0..15])'.format( + ovs_consts.RULES_EGRESS_TABLE, + ovsfw_consts.REG_NET) ) # DHCP discovery @@ -373,7 +430,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): self._add_flow( table=ovs_consts.BASE_EGRESS_TABLE, priority=80, - reg5=port.ofport, + reg_port=port.ofport, in_port=port.ofport, dl_type=dl_type, nw_proto=constants.PROTO_NUM_UDP, @@ -390,7 +447,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): table=ovs_consts.BASE_EGRESS_TABLE, priority=70, in_port=port.ofport, - reg5=port.ofport, + reg_port=port.ofport, dl_type=dl_type, nw_proto=constants.PROTO_NUM_UDP, tp_src=src_port, @@ -404,7 +461,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): priority=10, ct_state=ovsfw_consts.OF_STATE_NOT_TRACKED, in_port=port.ofport, - reg5=port.ofport, + reg_port=port.ofport, actions='drop' ) @@ -414,43 +471,80 @@ class OVSFirewallDriver(firewall.FirewallDriver): table=ovs_consts.ACCEPT_OR_INGRESS_TABLE, priority=100, dl_dst=port.mac, - actions='set_field:{:d}->reg5,resubmit(,{:d})'.format( - port.ofport, ovs_consts.BASE_INGRESS_TABLE), + actions='set_field:{:d}->reg{:d},resubmit(,{:d})'.format( + port.ofport, + ovsfw_consts.REG_PORT, + ovs_consts.BASE_INGRESS_TABLE), ) self._add_flow( table=ovs_consts.ACCEPT_OR_INGRESS_TABLE, priority=90, - reg5=port.ofport, - in_port=port.ofport, - actions='ct(commit,zone=NXM_NX_REG5[0..15]),normal' + reg_port=port.ofport, + ct_state=ovsfw_consts.OF_STATE_NEW_NOT_ESTABLISHED, + actions='ct(commit,zone=NXM_NX_REG{:d}[0..15]),normal'.format( + ovsfw_consts.REG_NET) + ) + self._add_flow( + table=ovs_consts.ACCEPT_OR_INGRESS_TABLE, + priority=80, + reg_port=port.ofport, + actions='normal' ) def _initialize_tracked_egress(self, port): + # Drop invalid packets self._add_flow( table=ovs_consts.RULES_EGRESS_TABLE, - priority=90, + priority=50, ct_state=ovsfw_consts.OF_STATE_INVALID, - actions='drop', + actions='drop' ) + # Drop traffic for removed sg rules + self._add_flow( + table=ovs_consts.RULES_EGRESS_TABLE, + priority=50, + reg_port=port.ofport, + ct_mark=ovsfw_consts.CT_MARK_INVALID, + actions='drop' + ) + for state in ( - ovsfw_consts.OF_STATE_ESTABLISHED, + ovsfw_consts.OF_STATE_ESTABLISHED_REPLY, ovsfw_consts.OF_STATE_RELATED, ): self._add_flow( table=ovs_consts.RULES_EGRESS_TABLE, - priority=80, + priority=50, ct_state=state, - reg5=port.ofport, - ct_zone=port.ofport, + ct_mark=ovsfw_consts.CT_MARK_NORMAL, + reg_port=port.ofport, + ct_zone=port.vlan_tag, actions='normal' ) + self._add_flow( + table=ovs_consts.RULES_EGRESS_TABLE, + priority=40, + reg_port=port.ofport, + ct_state=ovsfw_consts.OF_STATE_NOT_ESTABLISHED, + actions='drop' + ) + self._add_flow( + table=ovs_consts.RULES_EGRESS_TABLE, + priority=40, + reg_port=port.ofport, + ct_state=ovsfw_consts.OF_STATE_ESTABLISHED, + actions="ct(commit,zone=NXM_NX_REG{:d}[0..15]," + "exec(set_field:{:s}->ct_mark))".format( + ovsfw_consts.REG_NET, + ovsfw_consts.CT_MARK_INVALID) + ) def _initialize_ingress_ipv6_icmp(self, port): for icmp_type in constants.ICMPV6_ALLOWED_TYPES: self._add_flow( table=ovs_consts.BASE_INGRESS_TABLE, priority=100, - reg5=port.ofport, + reg_port=port.ofport, dl_dst=port.mac, dl_type=constants.ETHERTYPE_IPV6, nw_proto=constants.PROTO_NUM_IPV6_ICMP, @@ -464,7 +558,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): table=ovs_consts.BASE_INGRESS_TABLE, priority=100, dl_type=constants.ETHERTYPE_ARP, - reg5=port.ofport, + reg_port=port.ofport, dl_dst=port.mac, actions='output:{:d}'.format(port.ofport), ) @@ -477,7 +571,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): self._add_flow( table=ovs_consts.BASE_INGRESS_TABLE, priority=95, - reg5=port.ofport, + reg_port=port.ofport, dl_type=dl_type, nw_proto=constants.PROTO_NUM_UDP, tp_src=src_port, @@ -490,16 +584,18 @@ class OVSFirewallDriver(firewall.FirewallDriver): self._add_flow( table=ovs_consts.BASE_INGRESS_TABLE, priority=90, - reg5=port.ofport, + reg_port=port.ofport, dl_type=dl_type, ct_state=ovsfw_consts.OF_STATE_NOT_TRACKED, - actions='ct(table={:d},zone=NXM_NX_REG5[0..15])'.format( - ovs_consts.RULES_INGRESS_TABLE) + actions='ct(table={:d},zone=NXM_NX_REG{:d}[0..15])'.format( + ovs_consts.RULES_INGRESS_TABLE, + ovsfw_consts.REG_NET) ) self._add_flow( table=ovs_consts.BASE_INGRESS_TABLE, + ct_state=ovsfw_consts.OF_STATE_TRACKED, priority=80, - reg5=port.ofport, + reg_port=port.ofport, dl_dst=port.mac, actions='resubmit(,{:d})'.format(ovs_consts.RULES_INGRESS_TABLE) ) @@ -508,22 +604,49 @@ class OVSFirewallDriver(firewall.FirewallDriver): # Drop invalid packets self._add_flow( table=ovs_consts.RULES_INGRESS_TABLE, - priority=100, + priority=50, ct_state=ovsfw_consts.OF_STATE_INVALID, actions='drop' ) + # Drop traffic for removed sg rules + self._add_flow( + table=ovs_consts.RULES_INGRESS_TABLE, + priority=50, + reg_port=port.ofport, + ct_mark=ovsfw_consts.CT_MARK_INVALID, + actions='drop' + ) + # Allow established and related connections - for state in (ovsfw_consts.OF_STATE_ESTABLISHED, + for state in (ovsfw_consts.OF_STATE_ESTABLISHED_REPLY, ovsfw_consts.OF_STATE_RELATED): self._add_flow( table=ovs_consts.RULES_INGRESS_TABLE, - priority=80, + priority=50, dl_dst=port.mac, - reg5=port.ofport, + reg_port=port.ofport, ct_state=state, - ct_zone=port.ofport, + ct_mark=ovsfw_consts.CT_MARK_NORMAL, + ct_zone=port.vlan_tag, actions='output:{:d}'.format(port.ofport) ) + self._add_flow( + table=ovs_consts.RULES_INGRESS_TABLE, + priority=40, + reg_port=port.ofport, + ct_state=ovsfw_consts.OF_STATE_NOT_ESTABLISHED, + actions='drop' + ) + self._add_flow( + table=ovs_consts.RULES_INGRESS_TABLE, + priority=40, + reg_port=port.ofport, + ct_state=ovsfw_consts.OF_STATE_ESTABLISHED, + actions="ct(commit,zone=NXM_NX_REG{:d}[0..15]," + "exec(set_field:{:s}->ct_mark))".format( + ovsfw_consts.REG_NET, + ovsfw_consts.CT_MARK_INVALID) + ) def add_flows_from_rules(self, port): self._initialize_tracked_ingress(port) @@ -536,7 +659,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): LOG.debug("RULGEN: Rules generated for flow %s are %s", rule, flows) for flow in flows: - self._add_flow(**flow) + self._accept_flow(**flow) def create_rules_generator_for_port(self, port): for sec_group in port.sec_groups: @@ -554,6 +677,6 @@ class OVSFirewallDriver(firewall.FirewallDriver): self._delete_flows(table=ovs_consts.LOCAL_SWITCHING, dl_dst=port.mac) self._delete_flows(table=ovs_consts.LOCAL_SWITCHING, in_port=port.ofport) - self._delete_flows(reg5=port.ofport) + self._delete_flows(reg_port=port.ofport) self._delete_flows(table=ovs_consts.ACCEPT_OR_INGRESS_TABLE, dl_dst=port.mac) diff --git a/neutron/agent/linux/openvswitch_firewall/rules.py b/neutron/agent/linux/openvswitch_firewall/rules.py index d5c376286df..996bd8ead2d 100644 --- a/neutron/agent/linux/openvswitch_firewall/rules.py +++ b/neutron/agent/linux/openvswitch_firewall/rules.py @@ -46,7 +46,7 @@ def create_flows_from_rule_and_port(rule, port): flow_template = { 'priority': 70, 'dl_type': ovsfw_consts.ethertype_to_dl_type_map[ethertype], - 'reg5': port.ofport, + 'reg_port': port.ofport, } if is_valid_prefix(dst_ip_prefix): @@ -71,8 +71,7 @@ def create_protocol_flows(direction, flow_template, port, rule): if direction == firewall.INGRESS_DIRECTION: flow_template['table'] = ovs_consts.RULES_INGRESS_TABLE flow_template['dl_dst'] = port.mac - flow_template['actions'] = ('ct(commit,zone=NXM_NX_REG5[0..15]),' - 'output:{:d}'.format(port.ofport)) + flow_template['actions'] = "output:{:d}".format(port.ofport) elif direction == firewall.EGRESS_DIRECTION: flow_template['table'] = ovs_consts.RULES_EGRESS_TABLE flow_template['dl_src'] = port.mac diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/common/constants.py b/neutron/plugins/ml2/drivers/openvswitch/agent/common/constants.py index 650397027a2..72ba2e2bbe2 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/common/constants.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/common/constants.py @@ -136,3 +136,6 @@ OPENFLOW11 = "OpenFlow11" OPENFLOW12 = "OpenFlow12" OPENFLOW13 = "OpenFlow13" OPENFLOW14 = "OpenFlow14" + +# A placeholder for dead vlans. +DEAD_VLAN_TAG = p_const.MAX_VLAN_TAG + 1 diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py index 7effec238b4..8b7a7df1ce8 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py @@ -61,9 +61,6 @@ cfg.CONF.import_group('AGENT', 'neutron.plugins.ml2.drivers.openvswitch.' cfg.CONF.import_group('OVS', 'neutron.plugins.ml2.drivers.openvswitch.agent.' 'common.config') -# A placeholder for dead vlans. -DEAD_VLAN_TAG = p_const.MAX_VLAN_TAG + 1 - class _mac_mydialect(netaddr.mac_unix): word_fmt = '%.2x' @@ -346,7 +343,7 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin, continue net_uuid = local_vlan_map.get('net_uuid') if (net_uuid and net_uuid not in self._local_vlan_hints - and local_vlan != DEAD_VLAN_TAG): + and local_vlan != constants.DEAD_VLAN_TAG): self.available_local_vlans.remove(local_vlan) self._local_vlan_hints[local_vlan_map['net_uuid']] = \ local_vlan @@ -966,9 +963,10 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin, # Don't kill a port if it's already dead cur_tag = self.int_br.db_get_val("Port", port.port_name, "tag", log_errors=log_errors) - if cur_tag and cur_tag != DEAD_VLAN_TAG: + if cur_tag and cur_tag != constants.DEAD_VLAN_TAG: self.int_br.set_db_attribute("Port", port.port_name, "tag", - DEAD_VLAN_TAG, log_errors=log_errors) + constants.DEAD_VLAN_TAG, + log_errors=log_errors) self.int_br.drop_port(in_port=port.ofport) def setup_integration_br(self): diff --git a/neutron/tests/common/conn_testers.py b/neutron/tests/common/conn_testers.py index f8b302ef1e9..aaf0c0d3395 100644 --- a/neutron/tests/common/conn_testers.py +++ b/neutron/tests/common/conn_testers.py @@ -113,6 +113,9 @@ class ConnectionTester(fixtures.Fixture): def peer_ip_address(self): return self._peer.ip + def set_vm_default_gateway(self, default_gw): + self._vm.set_default_gateway(default_gw) + def flush_arp_tables(self): """Flush arptables in all used namespaces""" for machine in (self._peer, self._vm): @@ -188,7 +191,13 @@ class ConnectionTester(fixtures.Fixture): nc_tester = self._nc_testers.get(nc_params) if nc_tester: if nc_tester.is_established: - nc_tester.test_connectivity() + try: + nc_tester.test_connectivity() + except RuntimeError: + raise ConnectionTesterException( + "Established %s connection with protocol %s, source " + "port %s and destination port %s can no longer " + "communicate") else: nc_tester.stop_processes() raise ConnectionTesterException( @@ -282,6 +291,17 @@ class ConnectionTester(fixtures.Fixture): pinger = self._get_pinger(direction) return pinger.received + def assert_net_unreachable(self, direction, destination): + src_namespace, dst_address = self._get_namespace_and_address( + direction) + pinger = net_helpers.Pinger(src_namespace, destination, count=5) + pinger.start() + pinger.wait() + if not pinger.destination_unreachable: + raise ConnectionTesterException( + 'No Host Destination Unreachable packets were received when ' + 'sending icmp packets to %s' % destination) + class OVSConnectionTester(ConnectionTester): """Tester with OVS bridge in the middle diff --git a/neutron/tests/common/machine_fixtures.py b/neutron/tests/common/machine_fixtures.py index c812e5e5d85..e1293715a32 100644 --- a/neutron/tests/common/machine_fixtures.py +++ b/neutron/tests/common/machine_fixtures.py @@ -119,6 +119,9 @@ class FakeMachine(FakeMachineBase): self.port.link.set_address(mac_address) self.port.link.set_up() + def set_default_gateway(self, default_gw): + self.port.route.add_gateway(default_gw) + class PeerMachines(fixtures.Fixture): """Create 'amount' peered machines on an ip_cidr. diff --git a/neutron/tests/common/net_helpers.py b/neutron/tests/common/net_helpers.py index 8cd37f97597..695414aa17e 100644 --- a/neutron/tests/common/net_helpers.py +++ b/neutron/tests/common/net_helpers.py @@ -288,6 +288,8 @@ class Pinger(object): stats_pattern = re.compile( r'^(?P\d+) packets transmitted,.*(?P\d+) received.*$') + unreachable_pattern = re.compile( + r'.* Destination .* Unreachable') TIMEOUT = 15 def __init__(self, namespace, address, count=None, timeout=1): @@ -296,6 +298,7 @@ class Pinger(object): self.address = address self.count = count self.timeout = timeout + self.destination_unreachable = False self.sent = 0 self.received = 0 @@ -307,6 +310,10 @@ class Pinger(object): def _parse_stats(self): for line in self.proc.stdout: + if (not self.destination_unreachable and + self.unreachable_pattern.match(line)): + self.destination_unreachable = True + continue result = self.stats_pattern.match(line) if result: self.sent = int(result.group('trans')) @@ -331,6 +338,14 @@ class Pinger(object): self._wait_for_death() self._parse_stats() + def wait(self): + if self.count: + self._wait_for_death() + self._parse_stats() + else: + raise RuntimeError("Pinger is running infinitelly, use stop() " + "first") + class NetcatTester(object): TCP = n_const.PROTO_NAME_TCP diff --git a/neutron/tests/functional/agent/test_firewall.py b/neutron/tests/functional/agent/test_firewall.py index 791190b0ad6..1104e286931 100644 --- a/neutron/tests/functional/agent/test_firewall.py +++ b/neutron/tests/functional/agent/test_firewall.py @@ -19,9 +19,11 @@ import copy import functools +import random import netaddr from oslo_config import cfg +from oslo_log import log as logging import testscenarios from neutron.agent import firewall @@ -33,10 +35,10 @@ from neutron.common import constants from neutron.tests.common import conn_testers from neutron.tests.functional import base +LOG = logging.getLogger(__name__) load_tests = testscenarios.load_tests_apply_scenarios - reverse_direction = { conn_testers.ConnectionTester.INGRESS: conn_testers.ConnectionTester.EGRESS, @@ -46,17 +48,20 @@ reverse_transport_protocol = { conn_testers.ConnectionTester.TCP: conn_testers.ConnectionTester.UDP, conn_testers.ConnectionTester.UDP: conn_testers.ConnectionTester.TCP} - DEVICE_OWNER_COMPUTE = constants.DEVICE_OWNER_COMPUTE_PREFIX + 'fake' +VLAN_COUNT = 4096 -def skip_if_not_iptables(f): - @functools.wraps(f) - def wrap(self, *args, **kwargs): - if not hasattr(self, 'enable_ipset'): - self.skipTest("This test doesn't use iptables") - return f(self, *args, **kwargs) - return wrap +def skip_if_firewall(firewall_name): + def outter(f): + @functools.wraps(f) + def wrap(self, *args, **kwargs): + if self.firewall_name == firewall_name: + self.skipTest("This test doesn't use %s firewall" % + firewall_name) + return f(self, *args, **kwargs) + return wrap + return outter def _add_rule(sg_rules, base, port_range_min=None, port_range_max=None): @@ -73,18 +78,24 @@ class BaseFirewallTestCase(base.BaseSudoTestCase): MAC_SPOOFED = "fa:16:3e:9a:2f:48" scenarios = [('IptablesFirewallDriver without ipset', {'enable_ipset': False, - 'initialize': 'initialize_iptables'}), + 'initialize': 'initialize_iptables', + 'firewall_name': 'iptables'}), ('IptablesFirewallDriver with ipset', {'enable_ipset': True, - 'initialize': 'initialize_iptables'}), + 'initialize': 'initialize_iptables', + 'firewall_name': 'iptables'}), ('OVS Firewall Driver', - {'initialize': 'initialize_ovs'})] + {'initialize': 'initialize_ovs', + 'firewall_name': 'openvswitch'})] ip_cidr = None + vlan_range = set(range(VLAN_COUNT)) def setUp(self): cfg.CONF.register_opts(sg_cfg.security_group_opts, 'SECURITYGROUP') super(BaseFirewallTestCase, self).setUp() self.tester, self.firewall = getattr(self, self.initialize)() + if self.firewall_name == "openvswitch": + self.assign_vlan_to_peers() self.src_port_desc = self._create_port_description( self.tester.vm_port_id, [self.tester.vm_ip_address], @@ -117,6 +128,19 @@ class BaseFirewallTestCase(base.BaseSudoTestCase): firewall_drv = openvswitch_firewall.OVSFirewallDriver(tester.bridge) return tester, firewall_drv + def assign_vlan_to_peers(self): + vlan = self.get_not_used_vlan() + LOG.debug("Using %d vlan tag for this test", vlan) + self.tester.set_vm_tag(vlan) + self.tester.set_peer_tag(vlan) + + def get_not_used_vlan(self): + port_vlans = self.firewall.int_br.br.ovsdb.db_find( + 'Port', ('tag', '!=', '[]'), columns=['tag']).execute() + used_vlan_tags = {val['tag'] for val in port_vlans} + available_vlans = self.vlan_range - used_vlan_tags + return random.choice(list(available_vlans)) + @staticmethod def _create_port_description(port_id, ip_addresses, mac_address, sg_ids): return {'admin_state_up': True, @@ -142,7 +166,7 @@ class BaseFirewallTestCase(base.BaseSudoTestCase): class FirewallTestCase(BaseFirewallTestCase): ip_cidr = '192.168.0.1/24' - @skip_if_not_iptables + @skip_if_firewall('openvswitch') def test_rule_application_converges(self): sg_rules = [{'ethertype': 'IPv4', 'direction': 'egress'}, {'ethertype': 'IPv6', 'direction': 'egress'}, @@ -207,7 +231,7 @@ class FirewallTestCase(BaseFirewallTestCase): # and the new one was inserted in the correct position self.assertEqual([], self.firewall.iptables._apply()) - @skip_if_not_iptables + @skip_if_firewall('openvswitch') def test_rule_ordering_correct(self): sg_rules = [ {'ethertype': 'IPv4', 'direction': 'egress', 'protocol': 'tcp', @@ -280,7 +304,7 @@ class FirewallTestCase(BaseFirewallTestCase): self.tester.assert_no_connection(protocol=self.tester.ICMP, direction=self.tester.EGRESS) - @skip_if_not_iptables + @skip_if_firewall('openvswitch') def test_mac_spoofing_works_without_port_security_enabled(self): self.src_port_desc['port_security_enabled'] = False self.firewall.update_port_filter(self.src_port_desc) @@ -332,7 +356,7 @@ class FirewallTestCase(BaseFirewallTestCase): self.tester.assert_no_connection(protocol=self.tester.ICMP, direction=self.tester.EGRESS) - @skip_if_not_iptables + @skip_if_firewall('openvswitch') def test_ip_spoofing_works_without_port_security_enabled(self): self.src_port_desc['port_security_enabled'] = False self.firewall.update_port_filter(self.src_port_desc) @@ -456,7 +480,8 @@ class FirewallTestCase(BaseFirewallTestCase): direction=self.tester.EGRESS, src_port=source_port_max + 1) - def test_established_connection_is_not_cut(self): + @skip_if_firewall('iptables') + def test_established_connection_is_cut(self): port = 12345 sg_rules = [{'ethertype': constants.IPv4, 'direction': firewall.INGRESS_DIRECTION, @@ -470,7 +495,7 @@ class FirewallTestCase(BaseFirewallTestCase): self.tester.establish_connection(**connection) self._apply_security_group_rules(self.FAKE_SECURITY_GROUP_ID, list()) - self.tester.assert_established_connection(**connection) + self.tester.assert_no_established_connection(**connection) def test_preventing_firewall_blink(self): direction = self.tester.INGRESS @@ -514,9 +539,35 @@ class FirewallTestCase(BaseFirewallTestCase): self.tester.assert_no_connection(protocol=self.tester.ICMP, direction=self.tester.EGRESS) + def test_related_connection(self): + """Test ICMP net unreachable packets get back + + When destination address of ip traffic is not reachable, ICMP packets + are returned. This packets are marked as RELATED traffic by conntrack + and this test case validates such packets are not dropped by the + firewall as ingress ICMP packets are not allowed in this test case. The + used address below 1.2.3.4 is outside of subnet that is used in tester + object. + + """ + # Enable ip forwarding on the interface in order to reply with + # destionation net unreachable + self.tester._peer.execute([ + 'sysctl', '-w', 'net.ipv4.conf.%s.forwarding=1' % + self.tester._peer.port.name]) + self.tester.set_vm_default_gateway(self.tester.peer_ip_address) + vm_sg_rules = [{'ethertype': 'IPv4', 'direction': 'egress', + 'protocol': 'icmp'}] + self._apply_security_group_rules(self.FAKE_SECURITY_GROUP_ID, + vm_sg_rules) + + self.tester.assert_net_unreachable(self.tester.EGRESS, '1.2.3.4') + class FirewallTestCaseIPv6(BaseFirewallTestCase): - scenarios = [('OVS Firewall Driver', {'initialize': 'initialize_ovs'})] + scenarios = [('OVS Firewall Driver', + {'initialize': 'initialize_ovs', + 'firewall_name': 'openvswitch'})] ip_cidr = '2001:db8:aaaa::1/64' def test_icmp_from_specific_address(self): diff --git a/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py b/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py index bc31f48fd88..dd283e23b86 100644 --- a/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py +++ b/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py @@ -17,15 +17,34 @@ import testtools from neutron.agent.common import ovs_lib from neutron.agent import firewall +from neutron.agent.linux.openvswitch_firewall import constants as ovsfw_consts from neutron.agent.linux.openvswitch_firewall import firewall as ovsfw from neutron.common import constants from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants \ as ovs_consts from neutron.tests import base +TESTING_VLAN_TAG = 1 + def create_ofport(port_dict): - return ovsfw.OFPort(port_dict, mock.Mock(vif_mac='00:00:00:00:00:00')) + ovs_port = mock.Mock(vif_mac='00:00:00:00:00:00', port_name="port-name") + return ovsfw.OFPort(port_dict, ovs_port, vlan_tag=TESTING_VLAN_TAG) + + +class TestCreateRegNumbers(base.BaseTestCase): + def test_no_registers_defined(self): + flow = {'foo': 'bar'} + ovsfw.create_reg_numbers(flow) + self.assertEqual({'foo': 'bar'}, flow) + + def test_both_registers_defined(self): + flow = {'foo': 'bar', 'reg_port': 1, 'reg_net': 2} + expected_flow = {'foo': 'bar', + 'reg{:d}'.format(ovsfw_consts.REG_PORT): 1, + 'reg{:d}'.format(ovsfw_consts.REG_NET): 2} + ovsfw.create_reg_numbers(flow) + self.assertEqual(expected_flow, flow) class TestSecurityGroup(base.BaseTestCase): @@ -250,7 +269,14 @@ class TestOVSFirewallDriver(base.BaseTestCase): def test__add_flow_dl_type_formatted_to_string(self): dl_type = 0x0800 self.firewall._add_flow(dl_type=dl_type) - self.mock_bridge.br.add_flow.assert_called_once_with(dl_type="0x0800") + + def test__add_flow_registers_are_replaced(self): + self.firewall._add_flow(in_port=1, reg_port=1, reg_net=2) + expected_calls = {'in_port': 1, + 'reg{:d}'.format(ovsfw_consts.REG_PORT): 1, + 'reg{:d}'.format(ovsfw_consts.REG_NET): 2} + self.mock_bridge.br.add_flow.assert_called_once_with( + **expected_calls) def test__drop_all_unmatched_flows(self): self.firewall._drop_all_unmatched_flows() @@ -307,6 +333,14 @@ class TestOVSFirewallDriver(base.BaseTestCase): with testtools.ExpectedException(ovsfw.OVSFWPortNotFound): self.firewall.get_or_create_ofport(port_dict) + def test_get_or_create_ofport_not_tagged(self): + port_dict = { + 'device': 'port-id', + 'security_groups': [123, 456]} + self.mock_bridge.br.db_get_val.return_value = None + port = self.firewall.get_or_create_ofport(port_dict) + self.assertEqual(ovs_consts.DEAD_VLAN_TAG, port.vlan_tag) + def test_is_port_managed_managed_port(self): port_dict = {'device': 'port-id'} self.firewall.sg_port_map.ports[port_dict['device']] = object() @@ -324,25 +358,30 @@ class TestOVSFirewallDriver(base.BaseTestCase): self._prepare_security_group() self.firewall.prepare_port_filter(port_dict) exp_ingress_classifier = mock.call( - actions='set_field:{:d}->reg5,resubmit(,{:d})'.format( - self.port_ofport, ovs_consts.BASE_EGRESS_TABLE), + actions='set_field:{:d}->reg5,set_field:{:d}->reg6,' + 'resubmit(,{:d})'.format( + self.port_ofport, TESTING_VLAN_TAG, + ovs_consts.BASE_EGRESS_TABLE), in_port=self.port_ofport, priority=100, table=ovs_consts.LOCAL_SWITCHING) exp_egress_classifier = mock.call( - actions='set_field:{:d}->reg5,resubmit(,{:d})'.format( - self.port_ofport, ovs_consts.BASE_INGRESS_TABLE), + actions='set_field:{:d}->reg5,set_field:{:d}->reg6,' + 'resubmit(,{:d})'.format( + self.port_ofport, TESTING_VLAN_TAG, + ovs_consts.BASE_INGRESS_TABLE), dl_dst=self.port_mac, priority=90, table=ovs_consts.LOCAL_SWITCHING) filter_rule = mock.call( - actions='ct(commit,zone=NXM_NX_REG5[0..15]),output:{:d}'.format( + actions='output:{:d},ct(commit,zone=NXM_NX_REG6[0..15])'.format( self.port_ofport), dl_dst=self.port_mac, dl_type="0x{:04x}".format(constants.ETHERTYPE_IP), nw_proto=constants.PROTO_NUM_TCP, priority=70, reg5=self.port_ofport, + ct_state=ovsfw_consts.OF_STATE_NEW_NOT_ESTABLISHED, table=ovs_consts.RULES_INGRESS_TABLE, tcp_dst='0x007b') calls = self.mock_bridge.br.add_flow.call_args_list @@ -384,6 +423,7 @@ class TestOVSFirewallDriver(base.BaseTestCase): dl_type="0x{:04x}".format(constants.ETHERTYPE_IP), nw_proto=constants.PROTO_NUM_UDP, priority=70, + ct_state=ovsfw_consts.OF_STATE_NEW_NOT_ESTABLISHED, reg5=self.port_ofport, table=ovs_consts.RULES_EGRESS_TABLE) self.assertIn(filter_rule, add_calls) diff --git a/neutron/tests/unit/agent/linux/openvswitch_firewall/test_rules.py b/neutron/tests/unit/agent/linux/openvswitch_firewall/test_rules.py index 333ab4b2fac..89fe26c4ce6 100644 --- a/neutron/tests/unit/agent/linux/openvswitch_firewall/test_rules.py +++ b/neutron/tests/unit/agent/linux/openvswitch_firewall/test_rules.py @@ -22,6 +22,8 @@ from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants \ as ovs_consts from neutron.tests import base +TESTING_VLAN_TAG = 1 + class TestIsValidPrefix(base.BaseTestCase): def test_valid_prefix_ipv4(self): @@ -51,7 +53,8 @@ class TestCreateFlowsFromRuleAndPort(base.BaseTestCase): ovs_port = mock.Mock(vif_mac='00:00:00:00:00:00') ovs_port.ofport = 1 port_dict = {'device': 'port_id'} - self.port = ovsfw.OFPort(port_dict, ovs_port) + self.port = ovsfw.OFPort( + port_dict, ovs_port, vlan_tag=TESTING_VLAN_TAG) self.create_flows_mock = mock.patch.object( rules, 'create_protocol_flows').start() @@ -74,7 +77,7 @@ class TestCreateFlowsFromRuleAndPort(base.BaseTestCase): expected_template = { 'priority': 70, 'dl_type': constants.ETHERTYPE_IP, - 'reg5': self.port.ofport, + 'reg_port': self.port.ofport, } self._test_create_flows_from_rule_and_port_helper(rule, expected_template) @@ -89,7 +92,7 @@ class TestCreateFlowsFromRuleAndPort(base.BaseTestCase): expected_template = { 'priority': 70, 'dl_type': constants.ETHERTYPE_IP, - 'reg5': self.port.ofport, + 'reg_port': self.port.ofport, 'nw_src': '192.168.0.0/24', 'nw_dst': '10.0.0.1/32', } @@ -106,7 +109,7 @@ class TestCreateFlowsFromRuleAndPort(base.BaseTestCase): expected_template = { 'priority': 70, 'dl_type': constants.ETHERTYPE_IP, - 'reg5': self.port.ofport, + 'reg_port': self.port.ofport, 'nw_src': '192.168.0.0/24', } self._test_create_flows_from_rule_and_port_helper(rule, @@ -120,7 +123,7 @@ class TestCreateFlowsFromRuleAndPort(base.BaseTestCase): expected_template = { 'priority': 70, 'dl_type': constants.ETHERTYPE_IPV6, - 'reg5': self.port.ofport, + 'reg_port': self.port.ofport, } self._test_create_flows_from_rule_and_port_helper(rule, expected_template) @@ -135,7 +138,7 @@ class TestCreateFlowsFromRuleAndPort(base.BaseTestCase): expected_template = { 'priority': 70, 'dl_type': constants.ETHERTYPE_IPV6, - 'reg5': self.port.ofport, + 'reg_port': self.port.ofport, 'ipv6_src': '2001:db8:bbbb::1/64', 'ipv6_dst': '2001:db8:aaaa::1/64', } @@ -152,7 +155,7 @@ class TestCreateFlowsFromRuleAndPort(base.BaseTestCase): expected_template = { 'priority': 70, 'dl_type': constants.ETHERTYPE_IPV6, - 'reg5': self.port.ofport, + 'reg_port': self.port.ofport, 'ipv6_src': '2001:db8:bbbb::1/64', } self._test_create_flows_from_rule_and_port_helper(rule, @@ -165,7 +168,8 @@ class TestCreateProtocolFlows(base.BaseTestCase): ovs_port = mock.Mock(vif_mac='00:00:00:00:00:00') ovs_port.ofport = 1 port_dict = {'device': 'port_id'} - self.port = ovsfw.OFPort(port_dict, ovs_port) + self.port = ovsfw.OFPort( + port_dict, ovs_port, vlan_tag=TESTING_VLAN_TAG) def _test_create_protocol_flows_helper(self, direction, rule, expected_flows): @@ -181,7 +185,7 @@ class TestCreateProtocolFlows(base.BaseTestCase): expected_flows = [{ 'table': ovs_consts.RULES_INGRESS_TABLE, 'dl_dst': self.port.mac, - 'actions': 'ct(commit,zone=NXM_NX_REG5[0..15]),output:1', + 'actions': 'output:1', 'nw_proto': constants.PROTO_NUM_TCP, }] self._test_create_protocol_flows_helper( diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py index d2e1a97b40c..f485b2cd870 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py @@ -297,13 +297,13 @@ class TestOvsNeutronAgent(object): with mock.patch.object(self.agent, 'int_br') as int_br: int_br.db_get_val.return_value = cur_tag self.agent.port_dead(port) - if cur_tag is None or cur_tag == self.mod_agent.DEAD_VLAN_TAG: + if cur_tag is None or cur_tag == constants.DEAD_VLAN_TAG: self.assertFalse(int_br.set_db_attribute.called) self.assertFalse(int_br.drop_port.called) else: int_br.assert_has_calls([ mock.call.set_db_attribute("Port", mock.ANY, "tag", - self.mod_agent.DEAD_VLAN_TAG, + constants.DEAD_VLAN_TAG, log_errors=True), mock.call.drop_port(in_port=port.ofport), ]) @@ -312,7 +312,7 @@ class TestOvsNeutronAgent(object): self._test_port_dead() def test_port_dead_with_port_already_dead(self): - self._test_port_dead(self.mod_agent.DEAD_VLAN_TAG) + self._test_port_dead(constants.DEAD_VLAN_TAG) def test_port_dead_with_valid_tag(self): self._test_port_dead(cur_tag=1) @@ -1046,7 +1046,7 @@ class TestOvsNeutronAgent(object): # the main things we care about are that it gets put in the # dead vlan and gets blocked int_br.set_db_attribute.assert_any_call( - 'Port', vif.port_name, 'tag', self.mod_agent.DEAD_VLAN_TAG, + 'Port', vif.port_name, 'tag', constants.DEAD_VLAN_TAG, log_errors=False) int_br.drop_port.assert_called_once_with(in_port=vif.ofport) diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py index 278ce1c9f0f..7f43246494e 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py @@ -473,7 +473,7 @@ class TunnelTest(object): log_errors=True), mock.call.set_db_attribute( 'Port', VIF_PORT.port_name, - 'tag', self.mod_agent.DEAD_VLAN_TAG, + 'tag', constants.DEAD_VLAN_TAG, log_errors=True), mock.call.drop_port(in_port=VIF_PORT.ofport), ] From e2676ae8d188286b76f802d605f363e21011841a Mon Sep 17 00:00:00 2001 From: Kevin Benton Date: Fri, 25 Mar 2016 12:37:12 -0700 Subject: [PATCH 07/51] DVR: rebind port if ofport changes When binding is called in DVR, check to see if the port was previously wired under a different ofport. If it was, first unbind the old port and then bind the new one. Change-Id: I372158c4a6986295e396d849a2c9c5372b271e08 Closes-Bug: #1562467 (cherry picked from commit 4731dbbef1f615b9ce6d18315e8ca9810e8a772d) --- .../agent/ovs_dvr_neutron_agent.py | 6 ++ .../agent/test_ovs_neutron_agent.py | 73 ++++++++++++++----- 2 files changed, 59 insertions(+), 20 deletions(-) diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py index 8cb65f6527b..d5a62c28522 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py @@ -572,6 +572,12 @@ class OVSDVRNeutronAgent(object): local_vlan_map.network_type)) return + if (port.vif_id in self.local_ports and + self.local_ports[port.vif_id].ofport != port.ofport): + LOG.info(_LI("DVR: Port %(vif)s changed port number to " + "%(ofport)s, rebinding."), + {'vif': port.vif_id, 'ofport': port.ofport}) + self.unbind_port_from_dvr(port, local_vlan_map) if device_owner == n_const.DEVICE_OWNER_DVR_INTERFACE: self._bind_distributed_router_interface_port(port, local_vlan_map, diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py index d2e1a97b40c..72a020dc9f7 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py @@ -2336,6 +2336,58 @@ class TestOvsDvrNeutronAgent(object): def test_port_bound_for_dvr_with_csnat_ports(self): self._setup_for_dvr_test() + int_br, tun_br = self._port_bound_for_dvr_with_csnat_ports() + lvid = self.agent.local_vlan_map[self._net_uuid].vlan + expected_on_int_br = [ + mock.call.install_dvr_to_src_mac( + network_type='vxlan', + gateway_mac='aa:bb:cc:11:22:33', + dst_mac=self._port.vif_mac, + dst_port=self._port.ofport, + vlan_tag=lvid, + ), + ] + self._expected_port_bound(self._port, lvid, is_dvr=False) + self.assertEqual(expected_on_int_br, int_br.mock_calls) + expected_on_tun_br = [ + mock.call.provision_local_vlan( + network_type='vxlan', + lvid=lvid, + segmentation_id=None, + distributed=True, + ), + ] + self.assertEqual(expected_on_tun_br, tun_br.mock_calls) + + def test_port_bound_for_dvr_with_csnat_ports_ofport_change(self): + self._setup_for_dvr_test() + self._port_bound_for_dvr_with_csnat_ports() + # simulate a replug + self._port.ofport = 12 + int_br, tun_br = self._port_bound_for_dvr_with_csnat_ports() + lvid = self.agent.local_vlan_map[self._net_uuid].vlan + expected_on_int_br = [ + mock.call.delete_dvr_to_src_mac( + network_type='vxlan', + dst_mac=self._port.vif_mac, + vlan_tag=lvid, + ), + mock.call.install_dvr_to_src_mac( + network_type='vxlan', + gateway_mac='aa:bb:cc:11:22:33', + dst_mac=self._port.vif_mac, + dst_port=self._port.ofport, + vlan_tag=lvid, + ), + ] + self._expected_port_bound(self._port, lvid, is_dvr=False) + self.assertEqual(expected_on_int_br, int_br.mock_calls) + # a local vlan was already provisioned so there should be no new + # calls to tunbr + self.assertEqual([], tun_br.mock_calls) + # make sure ofport was updated + self.assertEqual(12, + self.agent.dvr_agent.local_ports[self._port.vif_id].ofport) + + def _port_bound_for_dvr_with_csnat_ports(self): int_br = mock.create_autospec(self.agent.int_br) tun_br = mock.create_autospec(self.agent.tun_br) int_br.set_db_attribute.return_value = True @@ -2361,26 +2413,7 @@ class TestOvsDvrNeutronAgent(object): None, None, self._fixed_ips, n_const.DEVICE_OWNER_ROUTER_SNAT, False) - lvid = self.agent.local_vlan_map[self._net_uuid].vlan - expected_on_int_br = [ - mock.call.install_dvr_to_src_mac( - network_type='vxlan', - gateway_mac='aa:bb:cc:11:22:33', - dst_mac=self._port.vif_mac, - dst_port=self._port.ofport, - vlan_tag=lvid, - ), - ] + self._expected_port_bound(self._port, lvid, is_dvr=False) - self.assertEqual(expected_on_int_br, int_br.mock_calls) - expected_on_tun_br = [ - mock.call.provision_local_vlan( - network_type='vxlan', - lvid=lvid, - segmentation_id=None, - distributed=True, - ), - ] - self.assertEqual(expected_on_tun_br, tun_br.mock_calls) + return int_br, tun_br def test_port_bound_for_dvr_with_csnat_ports_without_subnet(self): self._setup_for_dvr_test() From 211e0a65a0cf637ab58a20c91791b7eb6b8c8519 Mon Sep 17 00:00:00 2001 From: Jakub Libosvar Date: Mon, 29 Feb 2016 16:20:05 +0100 Subject: [PATCH 08/51] functional: Update ref used from ovs branch-2.5. OVS 2.5.0 has been released, but we need a later commit on branch-2.5 that fixes compilation with the latest kernel on ubuntu that backported some changes that broke compilation of 2.5.0. Change-Id: Id70db79a8450d4f0125dd500f7f6ab8d103d98c3 (cherry picked from commit 59b36ecca8f60996a60cd52f816573ace9b39309) --- neutron/tests/contrib/gate_hook.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/neutron/tests/contrib/gate_hook.sh b/neutron/tests/contrib/gate_hook.sh index 8fa392bd1d8..6301bb5d342 100644 --- a/neutron/tests/contrib/gate_hook.sh +++ b/neutron/tests/contrib/gate_hook.sh @@ -24,8 +24,10 @@ then configure_host_for_func_testing if [[ "$VENV" =~ "dsvm-functional" ]]; then - # Build from current branch-2.5 commit (2016-01-15) - OVS_BRANCH=eedd0ef239301f68964313e93dfd7ec41fc7814c + # The OVS_BRANCH variable is used by git checkout. In the case below + # we use a commit on branch-2.5 that fixes compilation with the + # latest ubuntu trusty kernel. + OVS_BRANCH="a35342879f1a7d8b1503d4945bd0791c58f5fc87" for package in openvswitch openvswitch-switch openvswitch-common; do if is_package_installed $package; then uninstall_package $package From 93d29d131c0234075ac547906f77900ce47cceec Mon Sep 17 00:00:00 2001 From: Clayton O'Neill Date: Thu, 24 Mar 2016 14:59:41 +0000 Subject: [PATCH 09/51] Don't delete br-int to br-tun patch on startup When starting up, we don't want to delete the patch port between br-int and br-tun unless we're also dropping the flows.. In liberty both of these bridges were switched to not dump flows on startup and to put the bridges in secure mode so that default flood flows are not installed when the bridge is created. Without this patch the patch port is torn down and not reinstalled until br-tun is setup again. Partial-Bug: #1514056 Change-Id: Ia518a99a2de5d1bda467fde57892c43970f88bcd (cherry picked from commit 8dce6a5c873c2c18e5a9c6165bf3974aead02588) --- .../drivers/openvswitch/agent/ovs_neutron_agent.py | 5 ++++- neutron/tests/functional/agent/test_l2_ovs_agent.py | 11 +++++++++++ .../ml2/drivers/openvswitch/agent/test_ovs_tunnel.py | 2 -- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py index 7effec238b4..5aca12be33f 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py @@ -983,8 +983,11 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin, self.int_br.set_secure_mode() self.int_br.setup_controllers(self.conf) - self.int_br.delete_port(self.conf.OVS.int_peer_patch_port) if self.conf.AGENT.drop_flows_on_start: + # Delete the patch port between br-int and br-tun if we're deleting + # the flows on br-int, so that traffic doesn't get flooded over + # while flows are missing. + self.int_br.delete_port(self.conf.OVS.int_peer_patch_port) self.int_br.delete_flows() self.int_br.setup_default_table() diff --git a/neutron/tests/functional/agent/test_l2_ovs_agent.py b/neutron/tests/functional/agent/test_l2_ovs_agent.py index 16658a4cdeb..07d1976b87c 100644 --- a/neutron/tests/functional/agent/test_l2_ovs_agent.py +++ b/neutron/tests/functional/agent/test_l2_ovs_agent.py @@ -180,6 +180,17 @@ class TestOVSAgent(base.OVSAgentTestFramework): self.agent.setup_integration_br() time.sleep(0.25) + def test_assert_patch_port_ofports_dont_change(self): + # When the integration bridge is setup, it should reuse the existing + # patch ports between br-int and br-tun. + self.setup_agent_and_ports(port_dicts=[], create_tunnels=True) + patch_int_ofport_before = self.agent.patch_int_ofport + patch_tun_ofport_before = self.agent.patch_tun_ofport + + self.setup_agent_and_ports(port_dicts=[], create_tunnels=True) + self.assertEqual(patch_int_ofport_before, self.agent.patch_int_ofport) + self.assertEqual(patch_tun_ofport_before, self.agent.patch_tun_ofport) + def test_noresync_after_port_gone(self): '''This will test the scenario where a port is removed after listing it but before getting vif info about it. diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py index 278ce1c9f0f..5238b7dfc89 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py @@ -182,7 +182,6 @@ class TunnelTest(object): mock.call.create(), mock.call.set_secure_mode(), mock.call.setup_controllers(mock.ANY), - mock.call.delete_port('patch-tun'), mock.call.setup_default_table(), ] @@ -628,7 +627,6 @@ class TunnelTestUseVethInterco(TunnelTest): mock.call.create(), mock.call.set_secure_mode(), mock.call.setup_controllers(mock.ANY), - mock.call.delete_port('patch-tun'), mock.call.setup_default_table(), ] From 7174bc4c2a0a31e9036ec130cb65f91d1e5009a4 Mon Sep 17 00:00:00 2001 From: venkata anil Date: Wed, 23 Mar 2016 15:24:01 +0000 Subject: [PATCH 10/51] Ignore exception when deleting linux bridge if doesn't exist Linux bridge is not handling RuntimeError exception when it is trying to delete network's bridge, which is deleted in parallel by nova. Fullstack test has similar scenario, it creates network's bridge for agent and deletes the bridge after the test, like nova. Linux bridge agent has to ignore RuntimeError exception if the bridge doesn't exist. Closes-bug: #1561040 Change-Id: I428384fd42181ff6bc33f29369a7ff5ec163b532 (cherry picked from commit 16b2ffdfd85eece8fb57a98d10bf35ad617d235a) --- .../agent/linuxbridge_neutron_agent.py | 24 +++++++++++++------ .../agent/test_linuxbridge_neutron_agent.py | 14 +++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py b/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py index c5d3e945900..6459619878e 100644 --- a/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py @@ -508,13 +508,23 @@ class LinuxBridgeManager(amb.CommonAgentManagerBase): elif interface not in physical_interfaces: self.delete_interface(interface) - LOG.debug("Deleting bridge %s", bridge_name) - if bridge_device.link.set_down(): - return - if bridge_device.delbr(): - return - LOG.debug("Done deleting bridge %s", bridge_name) - + try: + LOG.debug("Deleting bridge %s", bridge_name) + if bridge_device.link.set_down(): + return + if bridge_device.delbr(): + return + LOG.debug("Done deleting bridge %s", bridge_name) + except RuntimeError: + with excutils.save_and_reraise_exception() as ctxt: + if not bridge_device.exists(): + # the exception was likely a side effect of the bridge + # being removed by nova during handling, + # so we just return + ctxt.reraise = False + LOG.debug("Cannot delete bridge %s; it does not exist", + bridge_name) + return else: LOG.debug("Cannot delete bridge %s; it does not exist", bridge_name) diff --git a/neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py b/neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py index c64bc109098..57823b0c4e9 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py +++ b/neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py @@ -597,6 +597,20 @@ class TestLinuxBridgeManager(base.BaseTestCase): updif_fn.assert_called_with("eth1", "br0", "ips", "gateway") delif_fn.assert_called_with("vxlan-1002") + def test_delete_bridge_not_exist(self): + self.lbm.interface_mappings.update({}) + bridge_device = mock.Mock() + with mock.patch.object(bridge_lib, "BridgeDevice", + return_value=bridge_device): + bridge_device.exists.side_effect = [True, False] + bridge_device.get_interfaces.return_value = [] + bridge_device.link.set_down.side_effect = RuntimeError + self.lbm.delete_bridge("br0") + self.assertEqual(2, bridge_device.exists.call_count) + + bridge_device.exists.side_effect = [True, True] + self.assertRaises(RuntimeError, self.lbm.delete_bridge, "br0") + def test_delete_bridge_with_ip(self): bridge_device = mock.Mock() with mock.patch.object(ip_lib, "device_exists") as de_fn,\ From 90b9cd334b1b33df933bf1b61b38c6e087c431af Mon Sep 17 00:00:00 2001 From: Ihar Hrachyshka Date: Thu, 17 Mar 2016 16:20:52 +0100 Subject: [PATCH 11/51] port security: gracefully handle resources with no bindings Resources could be created before the extension was enabled in the setup. In that case, no bindings are created for them. In that case, we should gracefully return default (True) value when extracting the value using the mixin; and we should also create binding model on update request, if there is no existing binding model for the resource. While at it, introduced a constant to store the default value for port security (True) and changed several tests to use the constant instead of extracting it from extension resource map. Change-Id: I8607cdecdc16c5f94635c94e2f02700c732806eb Closes-Bug: #1509312 (cherry picked from commit b0519cf0ada3b3d9b76f84948f9ad3c142fc50be) --- neutron/db/portsecurity_db.py | 4 +- neutron/db/portsecurity_db_common.py | 41 ++++++---- neutron/extensions/portsecurity.py | 8 +- .../plugins/ml2/extensions/port_security.py | 12 +-- neutron/tests/unit/db/test_portsecurity_db.py | 47 ++++++++++++ .../unit/db/test_portsecurity_db_common.py | 76 +++++++++++++++++++ .../ml2/extensions/test_port_security.py | 17 +++-- .../unit/plugins/ml2/test_ext_portsecurity.py | 4 +- 8 files changed, 170 insertions(+), 39 deletions(-) create mode 100644 neutron/tests/unit/db/test_portsecurity_db.py create mode 100644 neutron/tests/unit/db/test_portsecurity_db_common.py diff --git a/neutron/db/portsecurity_db.py b/neutron/db/portsecurity_db.py index 343b5371050..944f5f89c01 100644 --- a/neutron/db/portsecurity_db.py +++ b/neutron/db/portsecurity_db.py @@ -29,8 +29,8 @@ class PortSecurityDbMixin(portsecurity_db_common.PortSecurityDbCommon): def _extend_port_security_dict(self, response_data, db_data): if ('port-security' in getattr(self, 'supported_extension_aliases', [])): - psec_value = db_data['port_security'][psec.PORTSECURITY] - response_data[psec.PORTSECURITY] = psec_value + super(PortSecurityDbMixin, self)._extend_port_security_dict( + response_data, db_data) def _determine_port_security_and_has_ip(self, context, port): """Returns a tuple of booleans (port_security_enabled, has_ip). diff --git a/neutron/db/portsecurity_db_common.py b/neutron/db/portsecurity_db_common.py index 6462227236f..a07439b8003 100644 --- a/neutron/db/portsecurity_db_common.py +++ b/neutron/db/portsecurity_db_common.py @@ -53,6 +53,13 @@ class NetworkSecurityBinding(model_base.BASEV2): class PortSecurityDbCommon(object): """Mixin class to add port security.""" + def _extend_port_security_dict(self, response_data, db_data): + if db_data.get('port_security') is None: + response_data[psec.PORTSECURITY] = psec.DEFAULT_PORT_SECURITY + else: + response_data[psec.PORTSECURITY] = ( + db_data['port_security'][psec.PORTSECURITY]) + def _process_network_port_security_create( self, context, network_req, network_res): with context.session.begin(subtransactions=True): @@ -78,52 +85,58 @@ class PortSecurityDbCommon(object): query = self._model_query(context, NetworkSecurityBinding) binding = query.filter( NetworkSecurityBinding.network_id == network_id).one() + return binding.port_security_enabled except exc.NoResultFound: - raise psec.PortSecurityBindingNotFound() - return binding.port_security_enabled + # NOTE(ihrachys) the resource may have been created before port + # security extension was enabled; return default value + return psec.DEFAULT_PORT_SECURITY def _get_port_security_binding(self, context, port_id): try: query = self._model_query(context, PortSecurityBinding) binding = query.filter( PortSecurityBinding.port_id == port_id).one() + return binding.port_security_enabled except exc.NoResultFound: - raise psec.PortSecurityBindingNotFound() - return binding.port_security_enabled + # NOTE(ihrachys) the resource may have been created before port + # security extension was enabled; return default value + return psec.DEFAULT_PORT_SECURITY def _process_port_port_security_update( self, context, port_req, port_res): - if psec.PORTSECURITY in port_req: - port_security_enabled = port_req[psec.PORTSECURITY] - else: + if psec.PORTSECURITY not in port_req: return + port_security_enabled = port_req[psec.PORTSECURITY] try: query = self._model_query(context, PortSecurityBinding) port_id = port_res['id'] binding = query.filter( PortSecurityBinding.port_id == port_id).one() - binding.port_security_enabled = port_security_enabled port_res[psec.PORTSECURITY] = port_security_enabled except exc.NoResultFound: - raise psec.PortSecurityBindingNotFound() + # NOTE(ihrachys) the resource may have been created before port + # security extension was enabled; create the binding model + self._process_port_port_security_create( + context, port_req, port_res) def _process_network_port_security_update( self, context, network_req, network_res): - if psec.PORTSECURITY in network_req: - port_security_enabled = network_req[psec.PORTSECURITY] - else: + if psec.PORTSECURITY not in network_req: return + port_security_enabled = network_req[psec.PORTSECURITY] try: query = self._model_query(context, NetworkSecurityBinding) network_id = network_res['id'] binding = query.filter( NetworkSecurityBinding.network_id == network_id).one() - binding.port_security_enabled = port_security_enabled network_res[psec.PORTSECURITY] = port_security_enabled except exc.NoResultFound: - raise psec.PortSecurityBindingNotFound() + # NOTE(ihrachys) the resource may have been created before port + # security extension was enabled; create the binding model + self._process_network_port_security_create( + context, network_req, network_res) def _make_network_port_security_dict(self, port_security, fields=None): res = {'network_id': port_security['network_id'], diff --git a/neutron/extensions/portsecurity.py b/neutron/extensions/portsecurity.py index fede653b99d..53c6a1563e8 100644 --- a/neutron/extensions/portsecurity.py +++ b/neutron/extensions/portsecurity.py @@ -18,6 +18,9 @@ from neutron.api.v2 import attributes from neutron.common import exceptions as nexception +DEFAULT_PORT_SECURITY = True + + class PortSecurityPortHasSecurityGroup(nexception.InUse): message = _("Port has security group associated. Cannot disable port " "security or ip address until security group is removed") @@ -28,16 +31,13 @@ class PortSecurityAndIPRequiredForSecurityGroups(nexception.InvalidInput): " address in order to use security groups.") -class PortSecurityBindingNotFound(nexception.InvalidExtensionEnv): - message = _("Port does not have port security binding.") - PORTSECURITY = 'port_security_enabled' EXTENDED_ATTRIBUTES_2_0 = { 'networks': { PORTSECURITY: {'allow_post': True, 'allow_put': True, 'convert_to': attributes.convert_to_boolean, 'enforce_policy': True, - 'default': True, + 'default': DEFAULT_PORT_SECURITY, 'is_visible': True}, }, 'ports': { diff --git a/neutron/plugins/ml2/extensions/port_security.py b/neutron/plugins/ml2/extensions/port_security.py index e5e499f3f3c..f3f73c1009f 100644 --- a/neutron/plugins/ml2/extensions/port_security.py +++ b/neutron/plugins/ml2/extensions/port_security.py @@ -41,8 +41,7 @@ class PortSecurityExtensionDriver(api.ExtensionDriver, def process_create_network(self, context, data, result): # Create the network extension attributes. if psec.PORTSECURITY not in data: - data[psec.PORTSECURITY] = (psec.EXTENDED_ATTRIBUTES_2_0['networks'] - [psec.PORTSECURITY]['default']) + data[psec.PORTSECURITY] = psec.DEFAULT_PORT_SECURITY self._process_network_port_security_create(context, data, result) def process_update_network(self, context, data, result): @@ -66,15 +65,6 @@ class PortSecurityExtensionDriver(api.ExtensionDriver, def extend_port_dict(self, session, db_data, result): self._extend_port_security_dict(result, db_data) - def _extend_port_security_dict(self, response_data, db_data): - if db_data.get('port_security') is None: - response_data[psec.PORTSECURITY] = ( - psec.EXTENDED_ATTRIBUTES_2_0['networks'] - [psec.PORTSECURITY]['default']) - else: - response_data[psec.PORTSECURITY] = ( - db_data['port_security'][psec.PORTSECURITY]) - def _determine_port_security(self, context, port): """Returns a boolean (port_security_enabled). diff --git a/neutron/tests/unit/db/test_portsecurity_db.py b/neutron/tests/unit/db/test_portsecurity_db.py new file mode 100644 index 00000000000..5ed483070f1 --- /dev/null +++ b/neutron/tests/unit/db/test_portsecurity_db.py @@ -0,0 +1,47 @@ +# 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 mock + +from neutron.db import portsecurity_db as pd +from neutron.db import portsecurity_db_common as pdc +from neutron.tests import base + +common = pdc.PortSecurityDbCommon + + +class FakePlugin(pd.PortSecurityDbMixin): + + supported_extension_aliases = ['port-security'] + + +class PortSecurityDbMixinTestCase(base.BaseTestCase): + + def setUp(self): + super(PortSecurityDbMixinTestCase, self).setUp() + self.plugin = FakePlugin() + + @mock.patch.object(common, '_extend_port_security_dict') + def test__extend_port_security_dict_relies_on_common(self, extend): + response = mock.Mock() + dbdata = mock.Mock() + self.plugin._extend_port_security_dict(response, dbdata) + extend.assert_called_once_with(response, dbdata) + + @mock.patch.object(common, '_extend_port_security_dict') + def test__extend_port_security_dict_ignored_if_extension_disabled(self, + extend): + response = mock.Mock() + dbdata = mock.Mock() + self.plugin.supported_extension_aliases = [] + self.plugin._extend_port_security_dict(response, dbdata) + self.assertFalse(extend.called) diff --git a/neutron/tests/unit/db/test_portsecurity_db_common.py b/neutron/tests/unit/db/test_portsecurity_db_common.py new file mode 100644 index 00000000000..a63ddcf19e0 --- /dev/null +++ b/neutron/tests/unit/db/test_portsecurity_db_common.py @@ -0,0 +1,76 @@ +# 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 mock +from sqlalchemy.orm import exc + +from neutron.db import portsecurity_db_common as pdc +from neutron.extensions import portsecurity as psec +from neutron.tests import base + + +common = pdc.PortSecurityDbCommon + + +class PortSecurityDbCommonTestCase(base.BaseTestCase): + + def setUp(self): + super(PortSecurityDbCommonTestCase, self).setUp() + self.common = common() + + def _test__get_security_binding_no_binding(self, getter): + port_sec_enabled = True + req = {psec.PORTSECURITY: port_sec_enabled} + res = {} + with mock.patch.object( + self.common, '_model_query', + create=True, + side_effect=exc.NoResultFound): + val = getter(req, res) + self.assertEqual(port_sec_enabled, val) + + def test__get_port_security_binding_no_binding(self): + self._test__get_security_binding_no_binding( + self.common._get_port_security_binding) + + def test__get_network_security_binding_no_binding(self): + self._test__get_security_binding_no_binding( + self.common._get_network_security_binding) + + def _test__process_security_update_no_binding(self, creator, updater): + req = {psec.PORTSECURITY: False} + res = {} + context = mock.Mock() + with mock.patch.object( + self.common, '_model_query', + create=True, + side_effect=exc.NoResultFound): + updater(context, req, res) + creator.assert_called_with(context, req, res) + + @mock.patch.object(common, '_process_port_port_security_create') + def test__process_port_port_security_update_no_binding(self, creator): + self._test__process_security_update_no_binding( + creator, + self.common._process_port_port_security_update) + + @mock.patch.object(common, '_process_network_port_security_create') + def test__process_network_port_security_update_no_binding(self, creator): + self._test__process_security_update_no_binding( + creator, + self.common._process_network_port_security_update) + + def test__extend_port_security_dict_no_port_security(self): + for db_data in ({'port_security': None, 'name': 'net1'}, {}): + response_data = {} + self.common._extend_port_security_dict(response_data, db_data) + self.assertTrue(response_data[psec.PORTSECURITY]) diff --git a/neutron/tests/unit/plugins/ml2/extensions/test_port_security.py b/neutron/tests/unit/plugins/ml2/extensions/test_port_security.py index 06ebd5baaf3..2f81d71445e 100644 --- a/neutron/tests/unit/plugins/ml2/extensions/test_port_security.py +++ b/neutron/tests/unit/plugins/ml2/extensions/test_port_security.py @@ -13,20 +13,27 @@ # License for the specific language governing permissions and limitations # under the License. +import mock + from neutron.extensions import portsecurity as psec from neutron.plugins.ml2.extensions import port_security from neutron.tests.unit.plugins.ml2 import test_plugin class TestML2ExtensionPortSecurity(test_plugin.Ml2PluginV2TestCase): - def test_extend_port_dict_no_port_security(self): - """Test _extend_port_security_dict won't crash - if port_security item is None - """ + def _test_extend_dict_no_port_security(self, func): + """Test extend_*_dict won't crash if port_security item is None.""" for db_data in ({'port_security': None, 'name': 'net1'}, {}): response_data = {} + session = mock.Mock() driver = port_security.PortSecurityExtensionDriver() - driver._extend_port_security_dict(response_data, db_data) + getattr(driver, func)(session, db_data, response_data) self.assertTrue(response_data[psec.PORTSECURITY]) + + def test_extend_port_dict_no_port_security(self): + self._test_extend_dict_no_port_security('extend_port_dict') + + def test_extend_network_dict_no_port_security(self): + self._test_extend_dict_no_port_security('extend_network_dict') diff --git a/neutron/tests/unit/plugins/ml2/test_ext_portsecurity.py b/neutron/tests/unit/plugins/ml2/test_ext_portsecurity.py index 5d5ef06cc77..94b7127094e 100644 --- a/neutron/tests/unit/plugins/ml2/test_ext_portsecurity.py +++ b/neutron/tests/unit/plugins/ml2/test_ext_portsecurity.py @@ -34,8 +34,6 @@ class PSExtDriverTestCase(test_plugin.Ml2PluginV2TestCase, def test_create_net_port_security_default(self): _core_plugin = manager.NeutronManager.get_plugin() admin_ctx = context.get_admin_context() - _default_value = (psec.EXTENDED_ATTRIBUTES_2_0['networks'] - [psec.PORTSECURITY]['default']) args = {'network': {'name': 'test', 'tenant_id': '', @@ -48,7 +46,7 @@ class PSExtDriverTestCase(test_plugin.Ml2PluginV2TestCase, finally: if network: _core_plugin.delete_network(admin_ctx, network['id']) - self.assertEqual(_default_value, _value) + self.assertEqual(psec.DEFAULT_PORT_SECURITY, _value) def test_create_port_with_secgroup_none_and_port_security_false(self): if self._skip_security_group: From aac460b0a7fec68fbb173ac8899274809e254a7a Mon Sep 17 00:00:00 2001 From: Vladimir Eremin Date: Thu, 17 Mar 2016 19:32:29 +0300 Subject: [PATCH 12/51] Allow to use several nics for physnet with SR-IOV Accordind specs and docs, SRIOV_NIC.physical_device_mappings is not limited to be a 1-1 mapping between physnets and NICs. However, implementation requires this. This bugfix unlocks 1-M mappings, so one physnet could be managed by many NICs. * introduced unique_keys in neutron.utils.parse_mappings * SRIOV_NIC.physical_device_mappings is parsed as dict with lists as values with parse_mappings(..., unique_keys=False) DocImpact Change-Id: I07b8682fdfe8389a35893cc662b87c94a00bd4a5 Closes-Bug: #1558626 (cherry picked from commit 46ddaf4288a1cac44d8afc0525b4ecb3ae2186a3) --- neutron/common/utils.py | 26 ++++++++++++------- .../mech_sriov/agent/eswitch_manager.py | 7 ++--- .../mech_sriov/agent/sriov_nic_agent.py | 6 +++-- neutron/tests/unit/common/test_utils.py | 9 +++++-- .../mech_sriov/agent/common/test_config.py | 11 ++++---- .../mech_sriov/agent/test_eswitch_manager.py | 6 ++--- .../mech_driver/test_mech_sriov_nic_switch.py | 4 +-- ...nics_for_one_physnet-3570aa67a60ce6c4.yaml | 8 ++++++ 8 files changed, 51 insertions(+), 26 deletions(-) create mode 100644 releasenotes/notes/sriov_allow_use_many_nics_for_one_physnet-3570aa67a60ce6c4.yaml diff --git a/neutron/common/utils.py b/neutron/common/utils.py index 03a953b7c48..0781fa48c93 100644 --- a/neutron/common/utils.py +++ b/neutron/common/utils.py @@ -214,12 +214,14 @@ def subprocess_popen(args, stdin=None, stdout=None, stderr=None, shell=False, close_fds=close_fds, env=env) -def parse_mappings(mapping_list, unique_values=True): +def parse_mappings(mapping_list, unique_values=True, unique_keys=True): """Parse a list of mapping strings into a dictionary. :param mapping_list: a list of strings of the form ':' :param unique_values: values must be unique if True - :returns: a dict mapping keys to values + :param unique_keys: keys must be unique if True, else implies that keys + and values are not unique + :returns: a dict mapping keys to values or to list of values """ mappings = {} for mapping in mapping_list: @@ -235,14 +237,20 @@ def parse_mappings(mapping_list, unique_values=True): value = split_result[1].strip() if not value: raise ValueError(_("Missing value in mapping: '%s'") % mapping) - if key in mappings: - raise ValueError(_("Key %(key)s in mapping: '%(mapping)s' not " - "unique") % {'key': key, 'mapping': mapping}) - if unique_values and value in mappings.values(): - raise ValueError(_("Value %(value)s in mapping: '%(mapping)s' " - "not unique") % {'value': value, + if unique_keys: + if key in mappings: + raise ValueError(_("Key %(key)s in mapping: '%(mapping)s' not " + "unique") % {'key': key, 'mapping': mapping}) - mappings[key] = value + if unique_values and value in mappings.values(): + raise ValueError(_("Value %(value)s in mapping: '%(mapping)s' " + "not unique") % {'value': value, + 'mapping': mapping}) + mappings[key] = value + else: + mappings.setdefault(key, []) + if value not in mappings[key]: + mappings[key].append(value) return mappings diff --git a/neutron/plugins/ml2/drivers/mech_sriov/agent/eswitch_manager.py b/neutron/plugins/ml2/drivers/mech_sriov/agent/eswitch_manager.py index ea0fac3d0be..201c3c32d94 100644 --- a/neutron/plugins/ml2/drivers/mech_sriov/agent/eswitch_manager.py +++ b/neutron/plugins/ml2/drivers/mech_sriov/agent/eswitch_manager.py @@ -340,9 +340,10 @@ class ESwitchManager(object): """ if exclude_devices is None: exclude_devices = {} - for phys_net, dev_name in six.iteritems(device_mappings): - self._create_emb_switch(phys_net, dev_name, - exclude_devices.get(dev_name, set())) + for phys_net, dev_names in six.iteritems(device_mappings): + for dev_name in dev_names: + self._create_emb_switch(phys_net, dev_name, + exclude_devices.get(dev_name, set())) def _create_emb_switch(self, phys_net, dev_name, exclude_devices): embedded_switch = EmbSwitch(phys_net, dev_name, exclude_devices) diff --git a/neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py b/neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py index 620d9c560a8..c6134baed7d 100644 --- a/neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py +++ b/neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py @@ -15,6 +15,7 @@ import collections +import itertools import socket import sys import time @@ -408,7 +409,7 @@ class SriovNicAgentConfigParser(object): Parse and validate the consistency in both mappings """ self.device_mappings = n_utils.parse_mappings( - cfg.CONF.SRIOV_NIC.physical_device_mappings) + cfg.CONF.SRIOV_NIC.physical_device_mappings, unique_keys=False) self.exclude_devices = config.parse_exclude_devices( cfg.CONF.SRIOV_NIC.exclude_devices) self._validate() @@ -419,7 +420,8 @@ class SriovNicAgentConfigParser(object): Validate that network_device in excluded_device exists in device mappings """ - dev_net_set = set(self.device_mappings.values()) + dev_net_set = set(itertools.chain.from_iterable( + six.itervalues(self.device_mappings))) for dev_name in self.exclude_devices.keys(): if dev_name not in dev_net_set: raise ValueError(_("Device name %(dev_name)s is missing from " diff --git a/neutron/tests/unit/common/test_utils.py b/neutron/tests/unit/common/test_utils.py index b5dcdf9960e..6e0024a1f11 100644 --- a/neutron/tests/unit/common/test_utils.py +++ b/neutron/tests/unit/common/test_utils.py @@ -32,8 +32,8 @@ from neutron.tests.common import helpers class TestParseMappings(base.BaseTestCase): - def parse(self, mapping_list, unique_values=True): - return utils.parse_mappings(mapping_list, unique_values) + def parse(self, mapping_list, unique_values=True, unique_keys=True): + return utils.parse_mappings(mapping_list, unique_values, unique_keys) def test_parse_mappings_fails_for_missing_separator(self): with testtools.ExpectedException(ValueError): @@ -73,6 +73,11 @@ class TestParseMappings(base.BaseTestCase): def test_parse_mappings_succeeds_for_no_mappings(self): self.assertEqual({}, self.parse([''])) + def test_parse_mappings_succeeds_for_nonuniq_key(self): + self.assertEqual({'key': ['val1', 'val2']}, + self.parse(['key:val1', 'key:val2', 'key:val2'], + unique_keys=False)) + class TestParseTunnelRangesMixin(object): TUN_MIN = None diff --git a/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/agent/common/test_config.py b/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/agent/common/test_config.py index a0a913fb4f3..68ac77bb3f1 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/agent/common/test_config.py +++ b/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/agent/common/test_config.py @@ -46,8 +46,8 @@ class TestSriovAgentConfig(base.BaseTestCase): DEVICE_MAPPING_WITH_SPACES_LIST = ['physnet7 : p7p1', 'physnet3 : p3p1 '] - DEVICE_MAPPING = {'physnet7': 'p7p1', - 'physnet3': 'p3p1'} + DEVICE_MAPPING = {'physnet7': ['p7p1'], + 'physnet3': ['p3p1']} def test_defaults(self): self.assertEqual(config.DEFAULT_DEVICE_MAPPINGS, @@ -62,7 +62,7 @@ class TestSriovAgentConfig(base.BaseTestCase): self.DEVICE_MAPPING_LIST, 'SRIOV_NIC') device_mappings = n_utils.parse_mappings( - cfg.CONF.SRIOV_NIC.physical_device_mappings) + cfg.CONF.SRIOV_NIC.physical_device_mappings, unique_keys=False) self.assertEqual(self.DEVICE_MAPPING, device_mappings) def test_device_mappings_with_error(self): @@ -70,14 +70,15 @@ class TestSriovAgentConfig(base.BaseTestCase): self.DEVICE_MAPPING_WITH_ERROR_LIST, 'SRIOV_NIC') self.assertRaises(ValueError, n_utils.parse_mappings, - cfg.CONF.SRIOV_NIC.physical_device_mappings) + cfg.CONF.SRIOV_NIC.physical_device_mappings, + unique_keys=False) def test_device_mappings_with_spaces(self): cfg.CONF.set_override('physical_device_mappings', self.DEVICE_MAPPING_WITH_SPACES_LIST, 'SRIOV_NIC') device_mappings = n_utils.parse_mappings( - cfg.CONF.SRIOV_NIC.physical_device_mappings) + cfg.CONF.SRIOV_NIC.physical_device_mappings, unique_keys=False) self.assertEqual(self.DEVICE_MAPPING, device_mappings) def test_exclude_devices(self): diff --git a/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/agent/test_eswitch_manager.py b/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/agent/test_eswitch_manager.py index bdaf9f3aa9e..b60637494c7 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/agent/test_eswitch_manager.py +++ b/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/agent/test_eswitch_manager.py @@ -31,7 +31,7 @@ class TestCreateESwitchManager(base.BaseTestCase): ('0000:06:00.3', 2)] def test_create_eswitch_mgr_fail(self): - device_mappings = {'physnet1': 'p6p1'} + device_mappings = {'physnet1': ['p6p1']} with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent." "eswitch_manager.PciOsWrapper.scan_vf_devices", side_effect=exc.InvalidDeviceError( @@ -45,7 +45,7 @@ class TestCreateESwitchManager(base.BaseTestCase): device_mappings, None) def test_create_eswitch_mgr_ok(self): - device_mappings = {'physnet1': 'p6p1'} + device_mappings = {'physnet1': ['p6p1']} with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent." "eswitch_manager.PciOsWrapper.scan_vf_devices", return_value=self.SCANNED_DEVICES),\ @@ -68,7 +68,7 @@ class TestESwitchManagerApi(base.BaseTestCase): def setUp(self): super(TestESwitchManagerApi, self).setUp() - device_mappings = {'physnet1': 'p6p1'} + device_mappings = {'physnet1': ['p6p1']} with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent." "eswitch_manager.PciOsWrapper.scan_vf_devices", return_value=self.SCANNED_DEVICES),\ diff --git a/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/mech_driver/test_mech_sriov_nic_switch.py b/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/mech_driver/test_mech_sriov_nic_switch.py index 310e8cc393f..211d4bf1ee4 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/mech_driver/test_mech_sriov_nic_switch.py +++ b/neutron/tests/unit/plugins/ml2/drivers/mech_sriov/mech_driver/test_mech_sriov_nic_switch.py @@ -61,10 +61,10 @@ class SriovNicSwitchMechanismBaseTestCase(base.AgentMechanismBaseTestCase): AGENT_TYPE = constants.AGENT_TYPE_NIC_SWITCH VLAN_SEGMENTS = base.AgentMechanismVlanTestCase.VLAN_SEGMENTS - GOOD_MAPPINGS = {'fake_physical_network': 'fake_device'} + GOOD_MAPPINGS = {'fake_physical_network': ['fake_device']} GOOD_CONFIGS = {'device_mappings': GOOD_MAPPINGS} - BAD_MAPPINGS = {'wrong_physical_network': 'wrong_device'} + BAD_MAPPINGS = {'wrong_physical_network': ['wrong_device']} BAD_CONFIGS = {'device_mappings': BAD_MAPPINGS} AGENTS = [{'alive': True, diff --git a/releasenotes/notes/sriov_allow_use_many_nics_for_one_physnet-3570aa67a60ce6c4.yaml b/releasenotes/notes/sriov_allow_use_many_nics_for_one_physnet-3570aa67a60ce6c4.yaml new file mode 100644 index 00000000000..c87afadb91d --- /dev/null +++ b/releasenotes/notes/sriov_allow_use_many_nics_for_one_physnet-3570aa67a60ce6c4.yaml @@ -0,0 +1,8 @@ +--- +prelude: > + Several NICs per physical network can be used with SR-IOV. +fixes: + - The 'physical_device_mappings' of sriov_nic configuration now can accept + more than one NIC per physical network. For example, if 'physnet2' is + connected to enp1s0f0 and enp1s0f1, 'physnet2:enp1s0f0,physnet2:enp1s0f1' + will be a valid option. From 38894cc7603f90ed8a5938e37fcc773c926fbfe4 Mon Sep 17 00:00:00 2001 From: Eugene Nikanorov Date: Mon, 21 Mar 2016 20:05:47 -0700 Subject: [PATCH 13/51] Retry updating agents table in case of deadlock Updating agents table is contantious operation which can fail often if mysql backend is in multimaster mode. This could lead to agents flapping and various issues such as sporadic reschedluing, port binding failures, etc. Change-Id: Ief392f9a09d86c185dc086055d2cbc1891ff1d7f Closes-Bug: #1560724 (cherry picked from commit d5e4013556c7144d347ece267c4bd3c8dc87b24f) --- neutron/db/agents_db.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/neutron/db/agents_db.py b/neutron/db/agents_db.py index 6f6f405ab0d..98b943b8768 100644 --- a/neutron/db/agents_db.py +++ b/neutron/db/agents_db.py @@ -33,6 +33,7 @@ from neutron.api.rpc.callbacks import version_manager from neutron.api.v2 import attributes from neutron.common import constants from neutron import context +from neutron.db import api as db_api from neutron.db import model_base from neutron.extensions import agent as ext_agent from neutron.extensions import availability_zone as az_ext @@ -434,6 +435,7 @@ class AgentExtRpcCallback(object): # Initialize RPC api directed to other neutron-servers self.server_versions_rpc = resources_rpc.ResourcesPushToServersRpcApi() + @db_api.retry_db_errors def report_state(self, context, **kwargs): """Report state from agent to server. From 05ac0125fe861fbfb09d48eec97a29539b51b4e2 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Fri, 25 Mar 2016 15:22:46 +0900 Subject: [PATCH 14/51] test_network_ip_availability: Skip IPv6 tests when configured so Use a class attribute known by the base class so that IPv6 tests are skipped appropriately when CONF.network_feature_enabled.ipv6 is False. Closes-Bug: #1561857 Change-Id: I93f76b7f7cd94ff484d2e4507500af97578ac71a (cherry picked from commit 61a5bcb52e23fa39839c30cb4f13f8a26e115516) --- neutron/tests/api/test_network_ip_availability.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/neutron/tests/api/test_network_ip_availability.py b/neutron/tests/api/test_network_ip_availability.py index 580916b9979..a7ac39bae5d 100644 --- a/neutron/tests/api/test_network_ip_availability.py +++ b/neutron/tests/api/test_network_ip_availability.py @@ -106,8 +106,6 @@ def calc_total_ips(prefix, ip_version): class NetworksIpAvailabilityIPv4Test(NetworksIpAvailabilityTest): - ip_version = lib_constants.IP_VERSION_4 - @test.attr(type='smoke') @test.idempotent_id('0f33cc8c-1bf6-47d1-9ce1-010618240599') def test_admin_network_availability_before_subnet(self): @@ -123,7 +121,7 @@ class NetworksIpAvailabilityIPv4Test(NetworksIpAvailabilityTest): net_name = data_utils.rand_name('network-') network = self.create_network(network_name=net_name) self.addCleanup(self.client.delete_network, network['id']) - subnet, prefix = self._create_subnet(network, self.ip_version) + subnet, prefix = self._create_subnet(network, self._ip_version) self.addCleanup(self.client.delete_subnet, subnet['id']) body = self.admin_client.list_network_ip_availabilities() used_ip = self._get_used_ips(network, body) @@ -134,7 +132,7 @@ class NetworksIpAvailabilityIPv4Test(NetworksIpAvailabilityTest): net_availability = self.admin_client.list_network_ip_availabilities() self._assert_total_and_used_ips( used_ip + 2, - calc_total_ips(prefix, self.ip_version), + calc_total_ips(prefix, self._ip_version), network, net_availability) @test.attr(type='smoke') @@ -143,7 +141,7 @@ class NetworksIpAvailabilityIPv4Test(NetworksIpAvailabilityTest): net_name = data_utils.rand_name('network-') network = self.create_network(network_name=net_name) self.addCleanup(self.client.delete_network, network['id']) - subnet, prefix = self._create_subnet(network, self.ip_version) + subnet, prefix = self._create_subnet(network, self._ip_version) self.addCleanup(self.client.delete_subnet, subnet['id']) port = self.client.create_port(network_id=network['id']) self.addCleanup(self._cleanUp_port, port['port']['id']) @@ -165,4 +163,4 @@ class NetworksIpAvailabilityIPv4Test(NetworksIpAvailabilityTest): class NetworksIpAvailabilityIPv6Test(NetworksIpAvailabilityIPv4Test): - ip_version = lib_constants.IP_VERSION_6 + _ip_version = lib_constants.IP_VERSION_6 From 33c01f4d49a4561bac56831483ac22c4a4b3f47d Mon Sep 17 00:00:00 2001 From: OpenStack Proposal Bot Date: Tue, 5 Apr 2016 06:48:18 +0000 Subject: [PATCH 15/51] Imported Translations from Zanata For more information about this automatic import see: https://wiki.openstack.org/wiki/Translations/Infrastructure Change-Id: Ief6281fde6ab1f72b26bfb11528fc64c71b407b9 --- neutron/locale/ja/LC_MESSAGES/neutron.po | 48 +++++++++++++----------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/neutron/locale/ja/LC_MESSAGES/neutron.po b/neutron/locale/ja/LC_MESSAGES/neutron.po index 1ba0ef8f5b1..747c66b7c85 100644 --- a/neutron/locale/ja/LC_MESSAGES/neutron.po +++ b/neutron/locale/ja/LC_MESSAGES/neutron.po @@ -18,13 +18,13 @@ # 笹原 昌美 , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0rc3.dev4\n" +"Project-Id-Version: neutron 8.0.0.0rc3.dev10\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-29 10:14+0000\n" +"POT-Creation-Date: 2016-03-31 01:13+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-03-30 05:19+0000\n" +"PO-Revision-Date: 2016-04-04 06:35+0000\n" "Last-Translator: 笹原 昌美 \n" "Language: ja\n" "Plural-Forms: nplurals=1; plural=0;\n" @@ -382,10 +382,10 @@ msgid "" "comments to generated iptables rules that describe each rule's purpose. " "System must support the iptables comments module for addition of comments." msgstr "" -"iptables ルールにコメントを追加します。この値を False に設定すると、各ルール" -"の目的を記述する生成済みの iptables ルールに対してコメントを追加することがで" -"きなくなります。システムでは、コメントの追加用に iptables コメントモジュール" -"がサポートされている必要があります。" +"iptables ルールにコメントを追加します。この値を False に設定すると、生成され" +"る iptalbes ルールにルールの目的を説明するコメントを追加しなくなります。シス" +"テムでは、コメントの追加用に iptables コメントモジュールがサポートされている" +"必要があります。" msgid "Address not present on interface" msgstr "インターフェース上に存在しないアドレス" @@ -803,7 +803,7 @@ msgstr "" "できません。" msgid "Cannot match priority on flow deletion or modification" -msgstr "flow の削除か設定の優先度が一致できません" +msgstr "flow の削除または変更時に、優先度の一致が見つかりません" msgid "Cannot mix IPv4 and IPv6 prefixes in a subnet pool." msgstr "" @@ -1246,6 +1246,7 @@ msgstr "ドメイン %(dns_domain)s が外部の DNS サービス内で見つか msgid "Domain to use for building the hostnames" msgstr "ホスト名の作成に使用するドメイン" +#, fuzzy msgid "" "Domain to use for building the hostnames. This option is deprecated. It has " "been moved to neutron.conf as dns_domain. It will be removed in a future " @@ -2705,8 +2706,9 @@ msgstr "" "トワークに複数の DHCP エージェントを割り当てるため、DHCP サービスの高可用性が" "実現します。" +#, fuzzy msgid "Number of RPC worker processes dedicated to state reports queue" -msgstr "レポートのキューを報告するためにのみ機能する RPC ワーカープロセスの数" +msgstr "レポート報告キュー専用の RPC ワーカープロセスの数" msgid "Number of RPC worker processes for service" msgstr "RPC サービスのワーカープロセス数" @@ -2776,8 +2778,8 @@ msgid "" "Number of separate API worker processes for service. If not specified, the " "default is equal to the number of CPUs available for best performance." msgstr "" -"サービスに使用する個別の API のワーカープロセスの数。指定されなかった場合、デ" -"フォルト値は性能を最大限得るために使用可能な CPU の数と一致します。" +"API サービスに使用する個別ワーカープロセスの数。指定されなかった場合、デフォ" +"ルト値は性能を最大限得るために使用可能な CPU の数と一致します。" msgid "" "Number of separate worker processes for metadata server (defaults to half of " @@ -3217,7 +3219,9 @@ msgstr "" "タリングをスキップして、直接コマンドを実行するには、'sudo' を使用します。" msgid "Root helper daemon application to use when possible." -msgstr "利用可能な場合に使用するルートヘルパーのデーモンアプリケーション。" +msgstr "" +"ルートヘルパーのデーモンアプリケーション。このアプリケーションは利用可能な場" +"合に使用します。" msgid "Root permissions are required to drop privileges." msgstr "特権を除去するにはルート許可が必要です。" @@ -3307,8 +3311,8 @@ msgid "" "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." msgstr "" -"サーバーにノードが状態を報告する間隔 (秒)。agent_down_time 未満である必要が" -"あります。agent_down_time の半分以下であれば最適です。" +"ノード状態をサーバーに報告する間隔 (秒)。agent_down_time 未満である必要があ" +"ります。agent_down_time の半分以下であれば最適です。" msgid "Seconds between running periodic tasks" msgstr "定期タスクの実行間隔 (秒)" @@ -3562,8 +3566,8 @@ msgid "" "between attempts." msgstr "" "DHCP エージェントが Neutron との間で状態の同期を取ることにより、一時的な通知" -"や RPC エラーからのリカバリーを行います。同期の試行の間の間隔は秒で表示されま" -"す。" +"や RPC エラーからのリカバリーを行います。間隔は同期の試行終了から次の試行まで" +"の秒数です。" msgid "" "The DHCP server can assist with providing metadata support on isolated " @@ -4158,18 +4162,18 @@ msgid "" "Use ipset to speed-up the iptables based security groups. Enabling ipset " "support requires that ipset is installed on L2 agent node." msgstr "" -"iptables ベースのセキュリティーグループの速度を向上させるには、ipset を使用し" -"ます。ipset へのサポートを有効化するには、L2 のエージェントノードに ipset を" -"インストールする必要があります。" +"iptables ベースのセキュリティーグループの速度を向上させるために、ipset を使用" +"します。ipset へのサポートを有効にするには、L2 のエージェントノードに ipset " +"をインストールする必要があります。" msgid "" "Use the root helper when listing the namespaces on a system. This may not be " "required depending on the security configuration. If the root helper is not " "required, set this to False for a performance improvement." msgstr "" -"システム上で名前空間を一覧表示する際にはルートヘルパーを使用します。セキュリ" -"ティー構成によっては、この処理は必要ない場合があります。ルートヘルパーが必要" -"ない場合は、パフォーマンスを高めるためにこの値を False に設定します。" +"システム上の名前空間を一覧表示する際にはルートヘルパーを使用します。セキュリ" +"ティー設定によっては、有効にする必要がない場合があります。ルートヘルパーが必" +"要ない場合は、パフォーマンスを高めるためにこの値を False に設定します。" msgid "" "Use veths instead of patch ports to interconnect the integration bridge to " From d93466923f3b5627c55510f9bc7229a7b584b430 Mon Sep 17 00:00:00 2001 From: Jakub Libosvar Date: Fri, 1 Apr 2016 14:53:03 +0000 Subject: [PATCH 16/51] ovsfw: Remove vlan tag before injecting packets to port Open vSwitch takes care of vlan tagging in case normal switching is used. When ingress traffic packets are accepted, the actions=output: is used but we need to explicitly take care of stripping out the vlan tags. Closes-Bug: 1564947 Change-Id: If3fc44c9fd1ac0f7bc9dfe9dc48e76352e981f8e (cherry picked from commit 0f9ec7b72a8ca173b760f20323f90bffefa91681) --- doc/source/devref/openvswitch_firewall.rst | 50 ++++++++++--------- .../linux/openvswitch_firewall/firewall.py | 13 ++--- .../agent/linux/openvswitch_firewall/rules.py | 2 +- .../openvswitch_firewall/test_firewall.py | 4 +- .../linux/openvswitch_firewall/test_rules.py | 2 +- 5 files changed, 37 insertions(+), 34 deletions(-) diff --git a/doc/source/devref/openvswitch_firewall.rst b/doc/source/devref/openvswitch_firewall.rst index 2ebccd99239..7fdfc8389d2 100644 --- a/doc/source/devref/openvswitch_firewall.rst +++ b/doc/source/devref/openvswitch_firewall.rst @@ -246,27 +246,28 @@ remaining egress connections are sent to normal switching. table=73, priority=0 actions=drop ``table 81`` is similar to ``table 71``, allows basic ingress traffic for -obtaining ip address and arp queries. Not tracked packets are sent to obtain -conntrack information. +obtaining ip address and arp queries. Note that vlan tag must be removed by +adding ``strip_vlan`` to actions list, prior to injecting packet directly to +port. Not tracked packets are sent to obtain conntrack information. :: - table=81, priority=100,arp,reg5=0x1,dl_dst=fa:16:3e:a4:22:10 actions=output:1 - table=81, priority=100,arp,reg5=0x2,dl_dst=fa:16:3e:24:57:c7 actions=output:2 - table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=130 actions=output:1 - table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=131 actions=output:1 - table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=132 actions=output:1 - table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=135 actions=output:1 - table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=136 actions=output:1 - table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=130 actions=output:2 - table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=131 actions=output:2 - table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=132 actions=output:2 - table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=135 actions=output:2 - table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=136 actions=output:2 - table=81, priority=95,udp,reg5=0x1,tp_src=67,tp_dst=68 actions=output:1 - table=81, priority=95,udp6,reg5=0x1,tp_src=547,tp_dst=546 actions=output:1 - table=81, priority=95,udp,reg5=0x2,tp_src=67,tp_dst=68 actions=output:2 - table=81, priority=95,udp6,reg5=0x2,tp_src=547,tp_dst=546 actions=output:2 + table=81, priority=100,arp,reg5=0x1,dl_dst=fa:16:3e:a4:22:10 actions=strip_vlan,output:1 + table=81, priority=100,arp,reg5=0x2,dl_dst=fa:16:3e:24:57:c7 actions=strip_vlan,output:2 + table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=130 actions=strip_vlan,output:1 + table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=131 actions=strip_vlan,output:1 + table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=132 actions=strip_vlan,output:1 + table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=135 actions=strip_vlan,output:1 + table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=136 actions=strip_vlan,output:1 + table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=130 actions=strip_vlan,output:2 + table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=131 actions=strip_vlan,output:2 + table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=132 actions=strip_vlan,output:2 + table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=135 actions=strip_vlan,output:2 + table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=136 actions=strip_vlan,output:2 + table=81, priority=95,udp,reg5=0x1,tp_src=67,tp_dst=68 actions=strip_vlan,output:1 + table=81, priority=95,udp6,reg5=0x1,tp_src=547,tp_dst=546 actions=strip_vlan,output:1 + table=81, priority=95,udp,reg5=0x2,tp_src=67,tp_dst=68 actions=strip_vlan,output:2 + table=81, priority=95,udp6,reg5=0x2,tp_src=547,tp_dst=546 actions=strip_vlan,output:2 table=81, priority=90,ct_state=-trk,ip,reg5=0x1 actions=ct(table=82,zone=NXM_NX_REG6[0..15]) table=81, priority=90,ct_state=-trk,ipv6,reg5=0x1 actions=ct(table=82,zone=NXM_NX_REG6[0..15]) table=81, priority=90,ct_state=-trk,ip,reg5=0x2 actions=ct(table=82,zone=NXM_NX_REG6[0..15]) @@ -282,8 +283,8 @@ connections. In this case we allow all icmp traffic coming from :: - table=82, priority=70,ct_state=+est-rel-rpl,icmp,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,nw_src=192.168.0.1 actions=output:2 - table=82, priority=70,ct_state=+new-est,icmp,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,nw_src=192.168.0.1 actions=output:2,ct(commit,zone=NXM_NX_REG6[0..15]) + table=82, priority=70,ct_state=+est-rel-rpl,icmp,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,nw_src=192.168.0.1 actions=strip_vlan,output:2 + table=82, priority=70,ct_state=+new-est,icmp,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,nw_src=192.168.0.1 actions=ct(commit,zone=NXM_NX_REG6[0..15]),strip_vlan,output:2 table=82, priority=50,ct_state=+inv+trk actions=drop The mechanism for dropping connections that are not allowed anymore is the @@ -293,10 +294,10 @@ same as in ``table 72``. table=82, priority=50,ct_mark=0x1,reg5=0x1 actions=drop table=82, priority=50,ct_mark=0x1,reg5=0x2 actions=drop - table=82, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x1,dl_dst=fa:16:3e:a4:22:10 actions=output:1 - table=82, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x2,dl_dst=fa:16:3e:24:57:c7 actions=output:2 - table=82, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x1,dl_dst=fa:16:3e:a4:22:10 actions=output:1 - table=82, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x2,dl_dst=fa:16:3e:24:57:c7 actions=output:2 + table=82, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x1,dl_dst=fa:16:3e:a4:22:10 actions=strip_vlan,output:1 + table=82, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x2,dl_dst=fa:16:3e:24:57:c7 actions=strip_vlan,output:2 + table=82, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x1,dl_dst=fa:16:3e:a4:22:10 actions=strip_vlan,output:1 + table=82, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x2,dl_dst=fa:16:3e:24:57:c7 actions=strip_vlan,output:2 table=82, priority=40,ct_state=-est,reg5=0x1 actions=drop table=82, priority=40,ct_state=+est,reg5=0x1 actions=ct(commit,zone=NXM_NX_REG6[0..15],exec(load:0x1->NXM_NX_CT_MARK[])) table=82, priority=40,ct_state=-est,reg5=0x2 actions=drop @@ -307,6 +308,7 @@ same as in ``table 72``. Future work ----------- + - Create fullstack tests with tunneling enabled - Conjunctions in Openflow rules can be created to decrease the number of rules needed for remote security groups - Masking the port range can be used to avoid generating a single rule per diff --git a/neutron/agent/linux/openvswitch_firewall/firewall.py b/neutron/agent/linux/openvswitch_firewall/firewall.py index b3ff55c8ae6..ec2402255b3 100644 --- a/neutron/agent/linux/openvswitch_firewall/firewall.py +++ b/neutron/agent/linux/openvswitch_firewall/firewall.py @@ -204,8 +204,9 @@ class OVSFirewallDriver(firewall.FirewallDriver): self._add_flow(**flow) flow['ct_state'] = ovsfw_consts.OF_STATE_NEW_NOT_ESTABLISHED if flow['table'] == ovs_consts.RULES_INGRESS_TABLE: - flow['actions'] += ',ct(commit,zone=NXM_NX_REG{:d}[0..15])'.format( - ovsfw_consts.REG_NET) + flow['actions'] = ( + 'ct(commit,zone=NXM_NX_REG{:d}[0..15]),{:s}'.format( + ovsfw_consts.REG_NET, flow['actions'])) self._add_flow(**flow) def _add_flow(self, **kwargs): @@ -549,7 +550,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): dl_type=constants.ETHERTYPE_IPV6, nw_proto=constants.PROTO_NUM_IPV6_ICMP, icmp_type=icmp_type, - actions='output:{:d}'.format(port.ofport), + actions='strip_vlan,output:{:d}'.format(port.ofport), ) def _initialize_ingress(self, port): @@ -560,7 +561,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): dl_type=constants.ETHERTYPE_ARP, reg_port=port.ofport, dl_dst=port.mac, - actions='output:{:d}'.format(port.ofport), + actions='strip_vlan,output:{:d}'.format(port.ofport), ) self._initialize_ingress_ipv6_icmp(port) @@ -576,7 +577,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): nw_proto=constants.PROTO_NUM_UDP, tp_src=src_port, tp_dst=dst_port, - actions='output:{:d}'.format(port.ofport), + actions='strip_vlan,output:{:d}'.format(port.ofport), ) # Track untracked @@ -628,7 +629,7 @@ class OVSFirewallDriver(firewall.FirewallDriver): ct_state=state, ct_mark=ovsfw_consts.CT_MARK_NORMAL, ct_zone=port.vlan_tag, - actions='output:{:d}'.format(port.ofport) + actions='strip_vlan,output:{:d}'.format(port.ofport) ) self._add_flow( table=ovs_consts.RULES_INGRESS_TABLE, diff --git a/neutron/agent/linux/openvswitch_firewall/rules.py b/neutron/agent/linux/openvswitch_firewall/rules.py index 996bd8ead2d..b096d64fe7c 100644 --- a/neutron/agent/linux/openvswitch_firewall/rules.py +++ b/neutron/agent/linux/openvswitch_firewall/rules.py @@ -71,7 +71,7 @@ def create_protocol_flows(direction, flow_template, port, rule): if direction == firewall.INGRESS_DIRECTION: flow_template['table'] = ovs_consts.RULES_INGRESS_TABLE flow_template['dl_dst'] = port.mac - flow_template['actions'] = "output:{:d}".format(port.ofport) + flow_template['actions'] = "strip_vlan,output:{:d}".format(port.ofport) elif direction == firewall.EGRESS_DIRECTION: flow_template['table'] = ovs_consts.RULES_EGRESS_TABLE flow_template['dl_src'] = port.mac diff --git a/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py b/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py index dd283e23b86..f7e67162afd 100644 --- a/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py +++ b/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py @@ -374,8 +374,8 @@ class TestOVSFirewallDriver(base.BaseTestCase): priority=90, table=ovs_consts.LOCAL_SWITCHING) filter_rule = mock.call( - actions='output:{:d},ct(commit,zone=NXM_NX_REG6[0..15])'.format( - self.port_ofport), + actions='ct(commit,zone=NXM_NX_REG6[0..15]),' + 'strip_vlan,output:{:d}'.format(self.port_ofport), dl_dst=self.port_mac, dl_type="0x{:04x}".format(constants.ETHERTYPE_IP), nw_proto=constants.PROTO_NUM_TCP, diff --git a/neutron/tests/unit/agent/linux/openvswitch_firewall/test_rules.py b/neutron/tests/unit/agent/linux/openvswitch_firewall/test_rules.py index 89fe26c4ce6..bab030c7134 100644 --- a/neutron/tests/unit/agent/linux/openvswitch_firewall/test_rules.py +++ b/neutron/tests/unit/agent/linux/openvswitch_firewall/test_rules.py @@ -185,7 +185,7 @@ class TestCreateProtocolFlows(base.BaseTestCase): expected_flows = [{ 'table': ovs_consts.RULES_INGRESS_TABLE, 'dl_dst': self.port.mac, - 'actions': 'output:1', + 'actions': 'strip_vlan,output:1', 'nw_proto': constants.PROTO_NUM_TCP, }] self._test_create_protocol_flows_helper( From 93cdf8eb559cf78895200b3ec6775afe60b6c638 Mon Sep 17 00:00:00 2001 From: Kevin Benton Date: Sun, 21 Feb 2016 21:31:59 -0800 Subject: [PATCH 17/51] Make L3 HA interface creation concurrency safe This patch creates a function to handle the creation of the L3HA interfaces for a router in a manner that handles the HA network not existing or an existing one being deleted by another worker before the interfaces could be created. Closes-Bug: #1548285 Change-Id: Ibac0c366362aa76615e448fbe11d6d6b031732fe (cherry-picked from commit 7512d8aa26a945a695e889e0a97c6414cec6ac10) --- neutron/common/utils.py | 88 ++++++++++++++++++++++ neutron/db/l3_hamode_db.py | 41 +++++++--- neutron/plugins/ml2/plugin.py | 28 +------ neutron/scheduler/l3_agent_scheduler.py | 18 ++++- neutron/tests/unit/db/test_l3_hamode_db.py | 78 +++++++++++++++++++ 5 files changed, 213 insertions(+), 40 deletions(-) diff --git a/neutron/common/utils.py b/neutron/common/utils.py index 03a953b7c48..c51fd323194 100644 --- a/neutron/common/utils.py +++ b/neutron/common/utils.py @@ -32,6 +32,7 @@ import signal import socket import sys import tempfile +import time import uuid import debtcollector @@ -39,6 +40,7 @@ from eventlet.green import subprocess import netaddr from oslo_concurrency import lockutils from oslo_config import cfg +from oslo_db import exception as db_exc from oslo_log import log as logging from oslo_utils import excutils from oslo_utils import importutils @@ -48,6 +50,7 @@ from stevedore import driver from neutron._i18n import _, _LE from neutron.common import constants as n_const +from neutron.db import api as db_api TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ" LOG = logging.getLogger(__name__) @@ -645,3 +648,88 @@ def port_rule_masking(port_min, port_max): _hex_format(mask))) return rules + + +def create_object_with_dependency(creator, dep_getter, dep_creator, + dep_id_attr): + """Creates an object that binds to a dependency while handling races. + + creator is a function that expected to take the result of either + dep_getter or dep_creator. + + The result of dep_getter and dep_creator must have an attribute of + dep_id_attr be used to determine if the dependency changed during object + creation. + + dep_getter should return None if the dependency does not exist + + dep_creator can raise a DBDuplicateEntry to indicate that a concurrent + create of the dependency occured and the process will restart to get the + concurrently created one + + This function will return both the created object and the dependency it + used/created. + + This function protects against all of the cases where the dependency can + be concurrently removed by catching exceptions and restarting the + process of creating the dependency if one no longer exists. It will + give up after neutron.db.api.MAX_RETRIES and raise the exception it + encounters after that. + + TODO(kevinbenton): currently this does not try to delete the dependency + it created. This matches the semantics of the HA network logic it is used + for but it should be modified to cleanup in the future. + """ + result, dependency, dep_id = None, None, None + for attempts in range(1, db_api.MAX_RETRIES + 1): + # we go to max + 1 here so the exception handlers can raise their + # errors at the end + try: + dependency = dep_getter() or dep_creator() + dep_id = getattr(dependency, dep_id_attr) + except db_exc.DBDuplicateEntry: + # dependency was concurrently created. + with excutils.save_and_reraise_exception() as ctx: + if attempts < db_api.MAX_RETRIES: + # sleep for a random time between 0 and 1 second to + # make sure a concurrent worker doesn't retry again + # at exactly the same time + time.sleep(random.uniform(0, 1)) + ctx.reraise = False + continue + try: + result = creator(dependency) + break + except Exception: + with excutils.save_and_reraise_exception() as ctx: + # check if dependency we tried to use was removed during + # object creation + if attempts < db_api.MAX_RETRIES: + dependency = dep_getter() + if not dependency or dep_id != getattr(dependency, + dep_id_attr): + ctx.reraise = False + return result, dependency + + +def transaction_guard(f): + """Ensures that the context passed in is not in a transaction. + + Various Neutron methods modifying resources have assumptions that they will + not be called inside of a transaction because they perform operations that + expect all data to be committed to the database (e.g. ML2 postcommit calls) + and/or they have side effects on external systems. + So calling them in a transaction can lead to consistency errors on failures + since the side effect will not be reverted on a DB rollback. + + If you receive this error, you must alter your code to handle the fact that + the thing you are calling can have side effects so using transactions to + undo on failures is not possible. + """ + @functools.wraps(f) + def inner(self, context, *args, **kwargs): + if context.session.is_active: + raise RuntimeError(_("Method cannot be called within a " + "transaction.")) + return f(self, context, *args, **kwargs) + return inner diff --git a/neutron/db/l3_hamode_db.py b/neutron/db/l3_hamode_db.py index d6ca793895c..695f4ae1084 100644 --- a/neutron/db/l3_hamode_db.py +++ b/neutron/db/l3_hamode_db.py @@ -257,6 +257,17 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin, ha_network = L3HARouterNetwork(tenant_id=tenant_id, network_id=network_id) context.session.add(ha_network) + # we need to check if someone else just inserted at exactly the + # same time as us because there is no constrain in L3HARouterNetwork + # that prevents multiple networks per tenant + with context.session.begin(subtransactions=True): + items = (context.session.query(L3HARouterNetwork). + filter_by(tenant_id=tenant_id).all()) + if len(items) > 1: + # we need to throw an error so our network is deleted + # and the process is started over where the existing + # network will be selected. + raise db_exc.DBDuplicateEntry(columns=['tenant_id']) return ha_network def _add_ha_network_settings(self, network): @@ -414,6 +425,19 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin, ha = cfg.CONF.l3_ha return ha + @n_utils.transaction_guard + def _create_ha_interfaces_and_ensure_network(self, context, router_db): + """Attach interfaces to a network while tolerating network deletes.""" + creator = functools.partial(self._create_ha_interfaces, + context, router_db) + dep_getter = functools.partial(self.get_ha_network, + context, router_db.tenant_id) + dep_creator = functools.partial(self._create_ha_network, + context, router_db.tenant_id) + dep_id_attr = 'network_id' + return n_utils.create_object_with_dependency( + creator, dep_getter, dep_creator, dep_id_attr) + def create_router(self, context, router): is_ha = self._is_ha(router['router']) router['router']['ha'] = is_ha @@ -423,14 +447,12 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin, if is_ha: try: router_db = self._get_router(context, router_dict['id']) - ha_network = self.get_ha_network(context, - router_db.tenant_id) - if not ha_network: - ha_network = self._create_ha_network(context, - router_db.tenant_id) + # the following returns interfaces and the network we only + # care about the network + ha_network = self._create_ha_interfaces_and_ensure_network( + context, router_db)[1] self._set_vr_id(context, router_db, ha_network) - self._create_ha_interfaces(context, router_db, ha_network) self._notify_ha_interfaces_updated(context, router_db.id) except Exception: with excutils.save_and_reraise_exception(): @@ -499,12 +521,9 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin, self._unbind_ha_router(context, router_id) if requested_ha_state: - if not ha_network: - ha_network = self._create_ha_network(context, - router_db.tenant_id) - + ha_network = self._create_ha_interfaces_and_ensure_network( + context, router_db)[1] self._set_vr_id(context, router_db, ha_network) - self._create_ha_interfaces(context, router_db, ha_network) self._notify_ha_interfaces_updated(context, router_db.id) else: self._delete_ha_interfaces(context, router_db.id) diff --git a/neutron/plugins/ml2/plugin.py b/neutron/plugins/ml2/plugin.py index 2150791d5ac..f11f8b87527 100644 --- a/neutron/plugins/ml2/plugin.py +++ b/neutron/plugins/ml2/plugin.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import functools - from eventlet import greenthread from oslo_config import cfg from oslo_db import api as oslo_db_api @@ -93,28 +91,6 @@ SERVICE_PLUGINS_REQUIRED_DRIVERS = { } -def transaction_guard(f): - """Ensures that the context passed in is not in a transaction. - - Many of ML2's methods modifying resources have assumptions that they will - not be called inside of a transaction because they perform operations that - expect all data to be committed to the database (all postcommit calls). - Calling them in a transaction can lead to consistency errors on failures - since the ML2 drivers will not be notified of a DB rollback. - - If you receive this error, you must alter your code to handle the fact that - ML2 calls have side effects so using transactions to undo on failures is - not possible. - """ - @functools.wraps(f) - def inner(self, context, *args, **kwargs): - if context.session.is_active: - raise RuntimeError(_("Method cannot be called within a " - "transaction.")) - return f(self, context, *args, **kwargs) - return inner - - class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, dvr_mac_db.DVRDbMixin, external_net_db.External_net_db_mixin, @@ -813,7 +789,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, LOG.exception(_LE("Exception auto-deleting subnet %s"), subnet_id) - @transaction_guard + @utils.transaction_guard def delete_network(self, context, id): # REVISIT(rkukura) The super(Ml2Plugin, self).delete_network() # function is not used because it auto-deletes ports and @@ -948,7 +924,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, self.mechanism_manager.update_subnet_postcommit(mech_context) return updated_subnet - @transaction_guard + @utils.transaction_guard def delete_subnet(self, context, id): # REVISIT(rkukura) The super(Ml2Plugin, self).delete_subnet() # function is not used because it deallocates the subnet's addresses diff --git a/neutron/scheduler/l3_agent_scheduler.py b/neutron/scheduler/l3_agent_scheduler.py index a9a399b6278..13145bf7059 100644 --- a/neutron/scheduler/l3_agent_scheduler.py +++ b/neutron/scheduler/l3_agent_scheduler.py @@ -15,6 +15,7 @@ import abc import collections +import functools import itertools import random @@ -255,13 +256,24 @@ class L3Scheduler(object): return False return True + def _add_port_from_net(self, plugin, ctxt, router_id, tenant_id, ha_net): + """small wrapper function to unpack network id from ha_network""" + return plugin.add_ha_port(ctxt, router_id, ha_net.network.id, + tenant_id) + def create_ha_port_and_bind(self, plugin, context, router_id, tenant_id, agent): """Creates and binds a new HA port for this agent.""" - ha_network = plugin.get_ha_network(context, tenant_id) + ctxt = context.elevated() + creator = functools.partial(self._add_port_from_net, + plugin, ctxt, router_id, tenant_id) + dep_getter = functools.partial(plugin.get_ha_network, ctxt, tenant_id) + dep_creator = functools.partial(plugin._create_ha_network, + ctxt, tenant_id) + dep_id_attr = 'network_id' try: - port_binding = plugin.add_ha_port(context.elevated(), router_id, - ha_network.network.id, tenant_id) + port_binding = utils.create_object_with_dependency( + creator, dep_getter, dep_creator, dep_id_attr)[0] with db_api.autonested_transaction(context.session): port_binding.l3_agent_id = agent['id'] except db_exc.DBDuplicateEntry: diff --git a/neutron/tests/unit/db/test_l3_hamode_db.py b/neutron/tests/unit/db/test_l3_hamode_db.py index b4149403a71..8a6a406c37d 100644 --- a/neutron/tests/unit/db/test_l3_hamode_db.py +++ b/neutron/tests/unit/db/test_l3_hamode_db.py @@ -14,9 +14,11 @@ import mock from oslo_config import cfg +from oslo_db import exception as db_exc from oslo_utils import uuidutils import sqlalchemy as sa from sqlalchemy import orm +import testtools from neutron.api.rpc.handlers import l3_rpc from neutron.api.v2 import attributes @@ -584,6 +586,82 @@ class L3HATestCase(L3HATestFramework): networks_after = self.core_plugin.get_networks(self.admin_ctx) self.assertEqual(networks_before, networks_after) + def test_create_ha_interfaces_and_ensure_network_net_exists(self): + router = self._create_router() + router_db = self.plugin._get_router(self.admin_ctx, router['id']) + with mock.patch.object(self.plugin, '_create_ha_network') as create: + self.plugin._create_ha_interfaces_and_ensure_network( + self.admin_ctx, router_db) + self.assertFalse(create.called) + + def test_create_ha_interfaces_and_ensure_network_concurrent_create(self): + # create a non-ha router so we can manually invoke the create ha + # interfaces call down below + router = self._create_router(ha=False) + router_db = self.plugin._get_router(self.admin_ctx, router['id']) + orig_create = self.plugin._create_ha_network + created_nets = [] + + def _create_ha_network(*args, **kwargs): + # create the network and then raise the error to simulate another + # worker creating the network before us. + created_nets.append(orig_create(*args, **kwargs)) + raise db_exc.DBDuplicateEntry(columns=['tenant_id']) + with mock.patch.object(self.plugin, '_create_ha_network', + new=_create_ha_network): + net = self.plugin._create_ha_interfaces_and_ensure_network( + self.admin_ctx, router_db)[1] + # ensure that it used the concurrently created network + self.assertEqual([net], created_nets) + + def _test_ensure_with_patched_int_create(self, _create_ha_interfaces): + # create a non-ha router so we can manually invoke the create ha + # interfaces call down below + router = self._create_router(ha=False) + router_db = self.plugin._get_router(self.admin_ctx, router['id']) + with mock.patch.object(self.plugin, '_create_ha_interfaces', + new=_create_ha_interfaces): + self.plugin._create_ha_interfaces_and_ensure_network( + self.admin_ctx, router_db) + self.assertTrue(_create_ha_interfaces.called) + + def test_create_ha_interfaces_and_ensure_network_concurrent_delete(self): + orig_create = self.plugin._create_ha_interfaces + + def _create_ha_interfaces(ctx, rdb, ha_net): + # concurrent delete on the first attempt + if not getattr(_create_ha_interfaces, 'called', False): + setattr(_create_ha_interfaces, 'called', True) + self.core_plugin.delete_network(self.admin_ctx, + ha_net['network_id']) + return orig_create(ctx, rdb, ha_net) + self._test_ensure_with_patched_int_create(_create_ha_interfaces) + + def test_create_ha_interfaces_and_ensure_network_concurrent_swap(self): + orig_create = self.plugin._create_ha_interfaces + + def _create_ha_interfaces(ctx, rdb, ha_net): + # concurrent delete on the first attempt + if not getattr(_create_ha_interfaces, 'called', False): + setattr(_create_ha_interfaces, 'called', True) + self.core_plugin.delete_network(self.admin_ctx, + ha_net['network_id']) + self.plugin._create_ha_network(self.admin_ctx, + rdb.tenant_id) + return orig_create(ctx, rdb, ha_net) + + self._test_ensure_with_patched_int_create(_create_ha_interfaces) + + def test_create_ha_network_tenant_binding_raises_duplicate(self): + router = self._create_router() + network = self.plugin.get_ha_network(self.admin_ctx, + router['tenant_id']) + self.plugin._create_ha_network_tenant_binding( + self.admin_ctx, 't1', network['network_id']) + with testtools.ExpectedException(db_exc.DBDuplicateEntry): + self.plugin._create_ha_network_tenant_binding( + self.admin_ctx, 't1', network['network_id']) + def test_create_ha_interfaces_binding_failure_rolls_back_ports(self): router = self._create_router() network = self.plugin.get_ha_network(self.admin_ctx, From 7b2fcaa1734bc1f26a1c4c2f0ace6fedbaa171e2 Mon Sep 17 00:00:00 2001 From: Armando Migliaccio Date: Fri, 1 Apr 2016 18:02:47 -0700 Subject: [PATCH 18/51] Use right class method in IP availability tests This should have been skip_checks. Spotted when dealing with fix for bug 1563883, argh. Change-Id: If609c285c2363967aba91a8ae1560d99391654d9 Related-bug: 1563883 (cherry picked from commit 2b0ce0ba8bf6abeb62654a00c12cfaad89f86e7c) --- neutron/tests/api/test_network_ip_availability.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neutron/tests/api/test_network_ip_availability.py b/neutron/tests/api/test_network_ip_availability.py index 580916b9979..c41a4782924 100644 --- a/neutron/tests/api/test_network_ip_availability.py +++ b/neutron/tests/api/test_network_ip_availability.py @@ -50,8 +50,8 @@ class NetworksIpAvailabilityTest(base.BaseAdminNetworkTest): """ @classmethod - def resource_setup(cls): - super(NetworksIpAvailabilityTest, cls).resource_setup() + def skip_checks(cls): + super(NetworksIpAvailabilityTest, cls).skip_checks() if not test.is_extension_enabled('network-ip-availability', 'network'): msg = "network-ip-availability extension not enabled." raise cls.skipException(msg) From 33d3b8ce76d942950e2f999a6040787483adf729 Mon Sep 17 00:00:00 2001 From: Kevin Benton Date: Fri, 1 Apr 2016 02:42:54 -0700 Subject: [PATCH 19/51] L3 agent: match format used by iptables This fixes the iptables rules generated by the L3 agent (SNAT, DNAT, set-mark and metadata), and the DHCP agent (checksum-fill) to match the format that will be returned by iptables-save to prevent excessive extra replacement work done by the iptables manager. It also fixes the iptables test that was not passing the expected arguments (-p PROTO -m PROTO) for block rules. A simple test was added to the L3 agent to ensure that the rules have converged during the normal lifecycle tests. Closes-Bug: #1566007 Change-Id: I5e8e27cdbf0d0448011881614671efe53bb1b6a1 (cherry picked from commit b8d520ffe2afbffe26b554bff55165531e36e758) --- neutron/agent/l3/router_info.py | 10 +++++----- neutron/agent/linux/dhcp.py | 2 +- neutron/agent/metadata/driver.py | 2 +- neutron/tests/functional/agent/l3/framework.py | 7 +++++++ neutron/tests/functional/agent/linux/test_iptables.py | 6 ++++-- neutron/tests/unit/agent/dhcp/test_agent.py | 2 +- neutron/tests/unit/agent/metadata/test_driver.py | 2 +- 7 files changed, 20 insertions(+), 11 deletions(-) diff --git a/neutron/agent/l3/router_info.py b/neutron/agent/l3/router_info.py index f767c7d139e..6544e6eccd6 100644 --- a/neutron/agent/l3/router_info.py +++ b/neutron/agent/l3/router_info.py @@ -140,16 +140,16 @@ class RouterInfo(object): return self.router.get(l3_constants.FLOATINGIP_KEY, []) def floating_forward_rules(self, floating_ip, fixed_ip): - return [('PREROUTING', '-d %s -j DNAT --to %s' % + return [('PREROUTING', '-d %s/32 -j DNAT --to-destination %s' % (floating_ip, fixed_ip)), - ('OUTPUT', '-d %s -j DNAT --to %s' % + ('OUTPUT', '-d %s/32 -j DNAT --to-destination %s' % (floating_ip, fixed_ip)), - ('float-snat', '-s %s -j SNAT --to %s' % + ('float-snat', '-s %s/32 -j SNAT --to-source %s' % (fixed_ip, floating_ip))] def floating_mangle_rules(self, floating_ip, fixed_ip, internal_mark): mark_traffic_to_floating_ip = ( - 'floatingip', '-d %s -j MARK --set-mark %s' % ( + 'floatingip', '-d %s -j MARK --set-xmark %s' % ( floating_ip, internal_mark)) mark_traffic_from_fixed_ip = ( 'FORWARD', '-s %s -j $float-snat' % fixed_ip) @@ -452,7 +452,7 @@ class RouterInfo(object): namespace=self.ns_name) def address_scope_mangle_rule(self, device_name, mark_mask): - return '-i %s -j MARK --set-mark %s' % (device_name, mark_mask) + return '-i %s -j MARK --set-xmark %s' % (device_name, mark_mask) def address_scope_filter_rule(self, device_name, mark_mask): return '-o %s -m mark ! --mark %s -j DROP' % ( diff --git a/neutron/agent/linux/dhcp.py b/neutron/agent/linux/dhcp.py index e08a1265489..11adffac1d1 100644 --- a/neutron/agent/linux/dhcp.py +++ b/neutron/agent/linux/dhcp.py @@ -1293,7 +1293,7 @@ class DeviceManager(object): """Ensure DHCP reply packets always have correct UDP checksums.""" iptables_mgr = iptables_manager.IptablesManager(use_ipv6=False, namespace=namespace) - ipv4_rule = ('-p udp --dport %d -j CHECKSUM --checksum-fill' + ipv4_rule = ('-p udp -m udp --dport %d -j CHECKSUM --checksum-fill' % constants.DHCP_RESPONSE_PORT) iptables_mgr.ipv4['mangle'].add_rule('POSTROUTING', ipv4_rule) iptables_mgr.apply() diff --git a/neutron/agent/metadata/driver.py b/neutron/agent/metadata/driver.py index cee81c0d868..2dd411a8dbc 100644 --- a/neutron/agent/metadata/driver.py +++ b/neutron/agent/metadata/driver.py @@ -63,7 +63,7 @@ class MetadataDriver(object): return [('PREROUTING', '-d 169.254.169.254/32 ' '-i %(interface_name)s ' '-p tcp -m tcp --dport 80 -j REDIRECT ' - '--to-port %(port)s' % + '--to-ports %(port)s' % {'interface_name': namespaces.INTERNAL_DEV_PREFIX + '+', 'port': port})] diff --git a/neutron/tests/functional/agent/l3/framework.py b/neutron/tests/functional/agent/l3/framework.py index d3b2e434f9a..eccc51de5c0 100644 --- a/neutron/tests/functional/agent/l3/framework.py +++ b/neutron/tests/functional/agent/l3/framework.py @@ -260,6 +260,7 @@ class L3AgentTestFramework(base.BaseSudoTestCase): self.assertTrue(self.floating_ips_configured(router)) self._assert_snat_chains(router) self._assert_floating_ip_chains(router) + self._assert_iptables_rules_converged(router) self._assert_extra_routes(router) ip_versions = [4, 6] if (ip_version == 6 or dual_stack) else [4] self._assert_onlink_subnet_routes(router, ip_versions) @@ -419,6 +420,12 @@ class L3AgentTestFramework(base.BaseSudoTestCase): self.assertFalse(router.iptables_manager.is_chain_empty( 'nat', 'float-snat')) + def _assert_iptables_rules_converged(self, router): + # if your code is failing on this line, it means you are not generating + # your iptables rules in the same format that iptables-save returns + # them. run iptables-save to see the format they should be in + self.assertFalse(router.iptables_manager.apply()) + def _assert_metadata_chains(self, router): metadata_port_filter = lambda rule: ( str(self.agent.conf.metadata_port) in rule.rule) diff --git a/neutron/tests/functional/agent/linux/test_iptables.py b/neutron/tests/functional/agent/linux/test_iptables.py index 2bbbedd4a92..95f1a9fdb48 100644 --- a/neutron/tests/functional/agent/linux/test_iptables.py +++ b/neutron/tests/functional/agent/linux/test_iptables.py @@ -31,7 +31,8 @@ class IptablesManagerTestCase(functional_base.BaseSudoTestCase): DIRECTION_CHAIN_MAPPER = {'ingress': 'INPUT', 'egress': 'OUTPUT'} PROTOCOL_BLOCK_RULE = '-p %s -j DROP' - PROTOCOL_PORT_BLOCK_RULE = '-p %s --dport %d -j DROP' + PROTOCOL_PORT_BLOCK_RULE = ('-p %(protocol)s -m %(protocol)s ' + '--dport %(port)d -j DROP') def setUp(self): super(IptablesManagerTestCase, self).setUp() @@ -73,7 +74,8 @@ class IptablesManagerTestCase(functional_base.BaseSudoTestCase): def _get_chain_and_rule(self, direction, protocol, port): chain = self.DIRECTION_CHAIN_MAPPER[direction] if port: - rule = self.PROTOCOL_PORT_BLOCK_RULE % (protocol, port) + rule = self.PROTOCOL_PORT_BLOCK_RULE % {'protocol': protocol, + 'port': port} else: rule = self.PROTOCOL_BLOCK_RULE % protocol return chain, rule diff --git a/neutron/tests/unit/agent/dhcp/test_agent.py b/neutron/tests/unit/agent/dhcp/test_agent.py index 286acb470d8..f7320ae0a2f 100644 --- a/neutron/tests/unit/agent/dhcp/test_agent.py +++ b/neutron/tests/unit/agent/dhcp/test_agent.py @@ -1319,7 +1319,7 @@ class TestDeviceManager(base.BaseTestCase): def test_setup_calls_fill_dhcp_udp_checksums(self): self._test_setup_helper(False) - rule = ('-p udp --dport %d -j CHECKSUM --checksum-fill' + rule = ('-p udp -m udp --dport %d -j CHECKSUM --checksum-fill' % const.DHCP_RESPONSE_PORT) expected = [mock.call.add_rule('POSTROUTING', rule)] self.mangle_inst.assert_has_calls(expected) diff --git a/neutron/tests/unit/agent/metadata/test_driver.py b/neutron/tests/unit/agent/metadata/test_driver.py index ea6047eb391..c38f54776c2 100644 --- a/neutron/tests/unit/agent/metadata/test_driver.py +++ b/neutron/tests/unit/agent/metadata/test_driver.py @@ -34,7 +34,7 @@ class TestMetadataDriverRules(base.BaseTestCase): def test_metadata_nat_rules(self): rules = ('PREROUTING', '-d 169.254.169.254/32 -i qr-+ ' - '-p tcp -m tcp --dport 80 -j REDIRECT --to-port 8775') + '-p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8775') self.assertEqual( [rules], metadata_driver.MetadataDriver.metadata_nat_rules(8775)) From 93d719a554d9b179636afccd25e1018b6e5d1cc3 Mon Sep 17 00:00:00 2001 From: Sreekumar S Date: Fri, 22 Jan 2016 19:09:49 +0530 Subject: [PATCH 20/51] SG protocol validation to allow numbers or names SG rule protocol provided is validated against the DB rules' protocols for both number and name. The filter provided to DB is modified so that it is queried for records with both the protocol name and number, instead of exactly the type provided with the input. The returned DB rule record's protocol field is validated against the supplied SG protocol field for both name or number. This way, user is still allowed to enter protocol name or number to create a rule, and API compatibility is maintained. Closes-Bug: #1215181 (cherry picked from commit 913a64cc1175b3bd7efc7abe34895c32bf39a696) Also squashed the following regression fix: === Don't drop 'protocol' from client supplied security_group_rule dict If protocol was present in the dict, but was None, then it was never re-instantiated after being popped out of the dict. This later resulted in KeyError when trying to access the key on the dict. Change-Id: I4985e7b54117bee3241d7365cb438197a09b9b86 Closes-Bug: #1566327 (cherry picked from commit 5a41caa47a080fdbc1801e2771163734b9790c57) === Change-Id: If4ad684e961433b8d9d3ec8fe2810585d3f6a093 --- neutron/common/constants.py | 2 ++ neutron/db/securitygroups_db.py | 24 ++++++++++++- .../tests/unit/db/test_securitygroups_db.py | 25 ++++++++++++++ .../unit/extensions/test_securitygroup.py | 34 +++++++++++++++++++ 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/neutron/common/constants.py b/neutron/common/constants.py index ecaea99cf0a..21d9b0869a7 100644 --- a/neutron/common/constants.py +++ b/neutron/common/constants.py @@ -128,6 +128,8 @@ IP_PROTOCOL_MAP = {PROTO_NAME_AH: PROTO_NUM_AH, IP_PROTOCOL_NAME_ALIASES = {PROTO_NAME_IPV6_ICMP_LEGACY: PROTO_NAME_IPV6_ICMP} +IP_PROTOCOL_NUM_TO_NAME_MAP = {str(v): k for k, v in IP_PROTOCOL_MAP.items()} + # List of ICMPv6 types that should be allowed by default: # Multicast Listener Query (130), # Multicast Listener Report (131), diff --git a/neutron/db/securitygroups_db.py b/neutron/db/securitygroups_db.py index 2758a9d717f..bfc98a216f2 100644 --- a/neutron/db/securitygroups_db.py +++ b/neutron/db/securitygroups_db.py @@ -424,6 +424,17 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase): protocol = constants.IP_PROTOCOL_NAME_ALIASES[protocol] return int(constants.IP_PROTOCOL_MAP.get(protocol, protocol)) + def _get_ip_proto_name_and_num(self, protocol): + if protocol is None: + return + protocol = str(protocol) + if protocol in constants.IP_PROTOCOL_MAP: + return [protocol, str(constants.IP_PROTOCOL_MAP.get(protocol))] + elif protocol in constants.IP_PROTOCOL_NUM_TO_NAME_MAP: + return [constants.IP_PROTOCOL_NUM_TO_NAME_MAP.get(protocol), + protocol] + return [protocol, protocol] + def _validate_port_range(self, rule): """Check that port_range is valid.""" if (rule['port_range_min'] is None and @@ -539,6 +550,10 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase): value = sgr.get(key) if value: res[key] = [value] + # protocol field will get corresponding name and number + value = sgr.get('protocol') + if value: + res['protocol'] = self._get_ip_proto_name_and_num(value) return res def _check_for_duplicate_rules(self, context, security_group_rules): @@ -569,9 +584,16 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase): # is changed which cannot be because other methods are already # relying on this behavior. Therefore, we do the filtering # below to check for these corner cases. + rule_dict = security_group_rule['security_group_rule'].copy() + sg_protocol = rule_dict.pop('protocol', None) for db_rule in db_rules: rule_id = db_rule.pop('id', None) - if (security_group_rule['security_group_rule'] == db_rule): + # remove protocol and match separately for number and type + db_protocol = db_rule.pop('protocol', None) + is_protocol_matching = ( + self._get_ip_proto_name_and_num(db_protocol) == + self._get_ip_proto_name_and_num(sg_protocol)) + if (is_protocol_matching and rule_dict == db_rule): raise ext_sg.SecurityGroupRuleExists(rule_id=rule_id) def _validate_ip_prefix(self, rule): diff --git a/neutron/tests/unit/db/test_securitygroups_db.py b/neutron/tests/unit/db/test_securitygroups_db.py index 473118c5e72..1dc282b71d1 100644 --- a/neutron/tests/unit/db/test_securitygroups_db.py +++ b/neutron/tests/unit/db/test_securitygroups_db.py @@ -91,6 +91,19 @@ class SecurityGroupDbMixinTestCase(testlib_api.SqlTestCase): self.mixin.create_security_group_rule( self.ctx, mock.MagicMock()) + def test__check_for_duplicate_rules_in_db_does_not_drop_protocol(self): + with mock.patch.object(self.mixin, 'get_security_group_rules', + return_value=[mock.Mock()]): + context = mock.Mock() + rule_dict = { + 'security_group_rule': {'protocol': None, + 'tenant_id': 'fake', + 'security_group_id': 'fake', + 'direction': 'fake'} + } + self.mixin._check_for_duplicate_rules_in_db(context, rule_dict) + self.assertIn('protocol', rule_dict['security_group_rule']) + def test_delete_security_group_rule_in_use(self): with mock.patch.object(registry, "notify") as mock_notify: mock_notify.side_effect = exceptions.CallbackFailure(Exception()) @@ -235,3 +248,15 @@ class SecurityGroupDbMixinTestCase(testlib_api.SqlTestCase): mock_notify.assert_has_calls([mock.call('security_group_rule', 'precommit_delete', mock.ANY, context=mock.ANY, security_group_rule_id=mock.ANY)]) + + def test_get_ip_proto_name_and_num(self): + protocols = [constants.PROTO_NAME_UDP, str(constants.PROTO_NUM_TCP), + 'blah', '111'] + protocol_names_nums = ( + [[constants.PROTO_NAME_UDP, str(constants.PROTO_NUM_UDP)], + [constants.PROTO_NAME_TCP, str(constants.PROTO_NUM_TCP)], + ['blah', 'blah'], ['111', '111']]) + + for i, protocol in enumerate(protocols): + self.assertEqual(protocol_names_nums[i], + self.mixin._get_ip_proto_name_and_num(protocol)) diff --git a/neutron/tests/unit/extensions/test_securitygroup.py b/neutron/tests/unit/extensions/test_securitygroup.py index 06cbdfafb96..c0e99852ccf 100644 --- a/neutron/tests/unit/extensions/test_securitygroup.py +++ b/neutron/tests/unit/extensions/test_securitygroup.py @@ -978,6 +978,40 @@ class TestSecurityGroups(SecurityGroupDBTestCase): self.assertIn(sgr['security_group_rule']['id'], res.json['NeutronError']['message']) + def test_create_security_group_rule_duplicate_rules_proto_name_num(self): + name = 'webservers' + description = 'my webservers' + with self.security_group(name, description) as sg: + security_group_id = sg['security_group']['id'] + with self.security_group_rule(security_group_id): + rule = self._build_security_group_rule( + sg['security_group']['id'], 'ingress', + const.PROTO_NAME_TCP, '22', '22') + self._create_security_group_rule(self.fmt, rule) + rule = self._build_security_group_rule( + sg['security_group']['id'], 'ingress', + const.PROTO_NUM_TCP, '22', '22') + res = self._create_security_group_rule(self.fmt, rule) + self.deserialize(self.fmt, res) + self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) + + def test_create_security_group_rule_duplicate_rules_proto_num_name(self): + name = 'webservers' + description = 'my webservers' + with self.security_group(name, description) as sg: + security_group_id = sg['security_group']['id'] + with self.security_group_rule(security_group_id): + rule = self._build_security_group_rule( + sg['security_group']['id'], 'ingress', + const.PROTO_NUM_UDP, '50', '100') + self._create_security_group_rule(self.fmt, rule) + rule = self._build_security_group_rule( + sg['security_group']['id'], 'ingress', + const.PROTO_NAME_UDP, '50', '100') + res = self._create_security_group_rule(self.fmt, rule) + self.deserialize(self.fmt, res) + self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) + def test_create_security_group_rule_min_port_greater_max(self): name = 'webservers' description = 'my webservers' From 905fd05f966e0c7d3851f59665e58746c50bad1e Mon Sep 17 00:00:00 2001 From: Swaminathan Vasudevan Date: Fri, 25 Mar 2016 12:38:13 -0700 Subject: [PATCH 21/51] DVR: Increase the link-local address pair range The current dvr_fip_ns.py file has FIP_LL_SUBNET configured with a subnet prefixlen of /23 which only allows 255 pairs of link-local addresses to be generated. If the number of routers per-node increases beyond the 255 limit it raises an assertion. This patch increases the link-local address cidr to be a /18 to allow for 8K routers. The new range was chosen to not overlap with the original, allowing for in-place upgrades without affecting existing routers. Closes-Bug: #1562110 Change-Id: I6e11622ea9cc74b1d2428757f16aa0de504ac31a (cherry picked from commit 7b1b8c2de57457c2ec1ed784165a3e10e24151cf) --- neutron/agent/l3/dvr_fip_ns.py | 2 +- neutron/agent/l3/item_allocator.py | 4 +++- neutron/agent/linux/keepalived.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/neutron/agent/l3/dvr_fip_ns.py b/neutron/agent/l3/dvr_fip_ns.py index e1b674108a9..3b9dce76d6b 100644 --- a/neutron/agent/l3/dvr_fip_ns.py +++ b/neutron/agent/l3/dvr_fip_ns.py @@ -32,7 +32,7 @@ FIP_2_ROUTER_DEV_PREFIX = 'fpr-' ROUTER_2_FIP_DEV_PREFIX = namespaces.ROUTER_2_FIP_DEV_PREFIX # Route Table index for FIPs FIP_RT_TBL = 16 -FIP_LL_SUBNET = '169.254.30.0/23' +FIP_LL_SUBNET = '169.254.64.0/18' # Rule priority range for FIPs FIP_PR_START = 32768 FIP_PR_END = FIP_PR_START + 40000 diff --git a/neutron/agent/l3/item_allocator.py b/neutron/agent/l3/item_allocator.py index 0d0ea74b5ef..14bf4de6338 100644 --- a/neutron/agent/l3/item_allocator.py +++ b/neutron/agent/l3/item_allocator.py @@ -77,7 +77,9 @@ class ItemAllocator(object): self.pool.update(self.remembered.values()) self.remembered.clear() if not self.pool: - # More than 256 routers on a compute node! + # The number of address pairs allocated from the + # pool depends upon the prefix length specified + # in FIP_LL_SUBNET raise RuntimeError("Cannot allocate item of type:" " %s from pool using file %s" % (self.ItemClass, self.state_file)) diff --git a/neutron/agent/linux/keepalived.py b/neutron/agent/linux/keepalived.py index 3c10f6a885c..976fc06fea6 100644 --- a/neutron/agent/linux/keepalived.py +++ b/neutron/agent/linux/keepalived.py @@ -30,7 +30,7 @@ VALID_AUTH_TYPES = ['AH', 'PASS'] HA_DEFAULT_PRIORITY = 50 PRIMARY_VIP_RANGE_SIZE = 24 # TODO(amuller): Use L3 agent constant when new constants module is introduced. -FIP_LL_SUBNET = '169.254.30.0/23' +FIP_LL_SUBNET = '169.254.64.0/18' KEEPALIVED_SERVICE_NAME = 'keepalived' GARP_MASTER_DELAY = 60 From 005d49d2f092039660a44896217a5c245dcc4685 Mon Sep 17 00:00:00 2001 From: Vincent Untz Date: Tue, 17 Nov 2015 17:47:56 +0100 Subject: [PATCH 22/51] Ensure metadata agent doesn't use SSL for UNIX socket The communication between the ns metadata proxy and the metadata agent is pure HTTP, and should not switch to HTTPS when neutron is using SSL. We're therefore telling wsgi.Server to forcefully disable SSL in that case. Change-Id: I2cb9fa231193bcd5c721c4d5cf0eb9c16e842349 Closes-Bug: #1514424 (cherry picked from commit 7a306e2918775ebb94d9e1408aaa2b7c3ed26fc6) --- neutron/agent/linux/utils.py | 2 +- neutron/tests/unit/test_wsgi.py | 22 ++++++++++++++++++++++ neutron/wsgi.py | 12 +++++++----- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/neutron/agent/linux/utils.py b/neutron/agent/linux/utils.py index 3166f1163f3..211177c390a 100644 --- a/neutron/agent/linux/utils.py +++ b/neutron/agent/linux/utils.py @@ -392,7 +392,7 @@ class UnixDomainWSGIServer(wsgi.Server): self._socket = None self._launcher = None self._server = None - super(UnixDomainWSGIServer, self).__init__(name) + super(UnixDomainWSGIServer, self).__init__(name, disable_ssl=True) def start(self, application, file_socket, workers, backlog, mode=None): self._socket = eventlet.listen(file_socket, diff --git a/neutron/tests/unit/test_wsgi.py b/neutron/tests/unit/test_wsgi.py index ff6515e2214..73076224159 100644 --- a/neutron/tests/unit/test_wsgi.py +++ b/neutron/tests/unit/test_wsgi.py @@ -175,6 +175,28 @@ class TestWSGIServer(base.BaseTestCase): server.stop() + def test_disable_ssl(self): + CONF.set_default('use_ssl', True) + + greetings = 'Hello, World!!!' + + def hello_world(env, start_response): + if env['PATH_INFO'] != '/': + start_response('404 Not Found', + [('Content-Type', 'text/plain')]) + return ['Not Found\r\n'] + start_response('200 OK', [('Content-Type', 'text/plain')]) + return [greetings] + + server = wsgi.Server("test_app", disable_ssl=True) + server.start(hello_world, 0, host="127.0.0.1") + + response = open_no_proxy('http://127.0.0.1:%d/' % server.port) + + self.assertEqual(greetings.encode('utf-8'), response.read()) + + server.stop() + @mock.patch.object(wsgi, 'eventlet') def test__run(self, eventlet_mock): server = wsgi.Server('test') diff --git a/neutron/wsgi.py b/neutron/wsgi.py index 8f349a926b7..5678c8d0244 100644 --- a/neutron/wsgi.py +++ b/neutron/wsgi.py @@ -76,9 +76,10 @@ def encode_body(body): class WorkerService(worker.NeutronWorker): """Wraps a worker to be handled by ProcessLauncher""" - def __init__(self, service, application): + def __init__(self, service, application, disable_ssl=False): self._service = service self._application = application + self._disable_ssl = disable_ssl self._server = None def start(self): @@ -89,7 +90,7 @@ class WorkerService(worker.NeutronWorker): # errors on service restart. # Duplicate a socket object to keep a file descriptor usable. dup_sock = self._service._socket.dup() - if CONF.use_ssl: + if CONF.use_ssl and not self._disable_ssl: dup_sock = sslutils.wrap(CONF, dup_sock) self._server = self._service.pool.spawn(self._service._run, self._application, @@ -112,10 +113,11 @@ class WorkerService(worker.NeutronWorker): class Server(object): """Server class to manage multiple WSGI sockets and applications.""" - def __init__(self, name, num_threads=1000): + def __init__(self, name, num_threads=1000, disable_ssl=False): # Raise the default from 8192 to accommodate large tokens eventlet.wsgi.MAX_HEADER_LINE = CONF.max_header_line self.num_threads = num_threads + self.disable_ssl = disable_ssl # Pool for a greenthread in which wsgi server will be running self.pool = eventlet.GreenPool(1) self.name = name @@ -123,7 +125,7 @@ class Server(object): # A value of 0 is converted to None because None is what causes the # wsgi server to wait forever. self.client_socket_timeout = CONF.client_socket_timeout or None - if CONF.use_ssl: + if CONF.use_ssl and not self.disable_ssl: sslutils.is_enabled(CONF) def _get_socket(self, host, port, backlog): @@ -186,7 +188,7 @@ class Server(object): self._launch(application, workers) def _launch(self, application, workers=0): - service = WorkerService(self, application) + service = WorkerService(self, application, self.disable_ssl) if workers < 1: # The API service should run in the current process. self._server = service From aafa702d2f389c0a4f3679df65be07940095ec29 Mon Sep 17 00:00:00 2001 From: Kevin Benton Date: Sun, 13 Mar 2016 20:52:09 -0700 Subject: [PATCH 23/51] Add IPAllocation object to session info to stop GC This adds the IPAllocation object created in the _store_ip_allocation method to the session info dictionary to prevent it from being immediately garbage collected. This is necessary because otherwise a new persistent object will be created when the fixed_ips relationship is referenced during the rest of the port create/update opertions. This persistent object will then interfere with a retry operation that uses the same session if it tries to create a conflicting record. By preventing the object from being garbage collected, the reference to fixed IPs will re-use the newly created sqlalchemy object instead which will properly be cleaned up on a rollback. This also removes the 'passive_delete' option from the fixed_ips relationship on ports because IPAllocation objects would now be left in the session after port deletes. At first glance, this might look like a performance penalty because fixed_ips would be looked up before port deletes; however, we already do that in the IPAM code as well as the ML2 code so this relationship is already being loaded on the delete_port operation. Closes-Bug: #1556178 Change-Id: Ieee1343bb90cf111c55e00b9cabc27943b46c350 (cherry picked from commit 7d9169967fca3d81076cf60eb772f4506735a218) --- neutron/db/db_base_plugin_common.py | 6 ++++++ neutron/db/models_v2.py | 3 ++- neutron/tests/unit/plugins/ml2/test_plugin.py | 1 - 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/neutron/db/db_base_plugin_common.py b/neutron/db/db_base_plugin_common.py index 0619fe0f990..6c63e5313b3 100644 --- a/neutron/db/db_base_plugin_common.py +++ b/neutron/db/db_base_plugin_common.py @@ -107,6 +107,12 @@ class DbBasePluginCommon(common_db_mixin.CommonDbMixin): subnet_id=subnet_id ) context.session.add(allocated) + # NOTE(kevinbenton): We add this to the session info so the sqlalchemy + # object isn't immediately garbage collected. Otherwise when the + # fixed_ips relationship is referenced a new persistent object will be + # added to the session that will interfere with retry operations. + # See bug 1556178 for details. + context.session.info.setdefault('allocated_ips', []).append(allocated) def _make_subnet_dict(self, subnet, fields=None, context=None): res = {'id': subnet['id'], diff --git a/neutron/db/models_v2.py b/neutron/db/models_v2.py index 2a78dbee146..7780c71e4f8 100644 --- a/neutron/db/models_v2.py +++ b/neutron/db/models_v2.py @@ -121,7 +121,8 @@ class Port(model_base.HasStandardAttributes, model_base.BASEV2, network_id = sa.Column(sa.String(36), sa.ForeignKey("networks.id"), nullable=False) fixed_ips = orm.relationship(IPAllocation, backref='port', lazy='joined', - passive_deletes='all') + cascade='all, delete-orphan') + mac_address = sa.Column(sa.String(32), nullable=False) admin_state_up = sa.Column(sa.Boolean(), nullable=False) status = sa.Column(sa.String(16), nullable=False) diff --git a/neutron/tests/unit/plugins/ml2/test_plugin.py b/neutron/tests/unit/plugins/ml2/test_plugin.py index 22c47d42d58..6e05cbde308 100644 --- a/neutron/tests/unit/plugins/ml2/test_plugin.py +++ b/neutron/tests/unit/plugins/ml2/test_plugin.py @@ -798,7 +798,6 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase): self._test_operation_resillient_to_ipallocation_failure(do_request) - @testtools.skip('bug/1556178') def _test_operation_resillient_to_ipallocation_failure(self, func): from sqlalchemy import event From 19ea6ba92379168e1bfff7a7235119cfbbc0172c Mon Sep 17 00:00:00 2001 From: Hynek Mlnarik Date: Wed, 23 Mar 2016 14:51:59 +0100 Subject: [PATCH 24/51] Remove obsolete keepalived PID files before start keepalived refuses to start and claims "daemon already started" when there is already a process with the same PID as found in either the VRRP or the main process PID file. This happens even in case when the new process is not keepalived. The situation can happen when the neutron node is reset and the obsolete PID files are not cleaned before neutron is started. This commit adds PID file cleanup before keepalived start. Closes-Bug: 1561046 Change-Id: Ib6b6f2fe76fe82253f195c9eab6b243d9eb76fa2 (cherry picked from commit e98fabb5836b12bc40a2b64a2668893ea73c2320) --- neutron/agent/linux/keepalived.py | 22 ++++++-- .../functional/agent/linux/test_keepalived.py | 54 +++++++++++++++++++ 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/neutron/agent/linux/keepalived.py b/neutron/agent/linux/keepalived.py index 3c10f6a885c..ed02a9a65c8 100644 --- a/neutron/agent/linux/keepalived.py +++ b/neutron/agent/linux/keepalived.py @@ -20,7 +20,7 @@ import netaddr from oslo_config import cfg from oslo_log import log as logging -from neutron._i18n import _ +from neutron._i18n import _, _LE from neutron.agent.linux import external_process from neutron.common import exceptions from neutron.common import utils as common_utils @@ -367,6 +367,18 @@ class KeepalivedManager(object): return config_path + @staticmethod + def _safe_remove_pid_file(pid_file): + try: + os.remove(pid_file) + except OSError as e: + if e.errno != errno.ENOENT: + LOG.error(_LE("Could not delete file %s, keepalived can " + "refuse to start."), pid_file) + + def get_vrrp_pid_file_name(self, base_pid_file): + return '%s-vrrp' % base_pid_file + def get_conf_on_disk(self): config_path = self.get_full_config_file_path('keepalived.conf') try: @@ -381,7 +393,7 @@ class KeepalivedManager(object): keepalived_pm = self.get_process() vrrp_pm = self._get_vrrp_process( - '%s-vrrp' % keepalived_pm.get_pid_file_name()) + self.get_vrrp_pid_file_name(keepalived_pm.get_pid_file_name())) keepalived_pm.default_cmd_callback = ( self._get_keepalived_process_callback(vrrp_pm, config_path)) @@ -424,10 +436,14 @@ class KeepalivedManager(object): # and spawn keepalived successfully. if vrrp_pm.active: vrrp_pm.disable() + + self._safe_remove_pid_file(pid_file) + self._safe_remove_pid_file(self.get_vrrp_pid_file_name(pid_file)) + cmd = ['keepalived', '-P', '-f', config_path, '-p', pid_file, - '-r', '%s-vrrp' % pid_file] + '-r', self.get_vrrp_pid_file_name(pid_file)] return cmd return callback diff --git a/neutron/tests/functional/agent/linux/test_keepalived.py b/neutron/tests/functional/agent/linux/test_keepalived.py index eacbbaf0222..ac1fe80cc92 100644 --- a/neutron/tests/functional/agent/linux/test_keepalived.py +++ b/neutron/tests/functional/agent/linux/test_keepalived.py @@ -13,6 +13,10 @@ # License for the specific language governing permissions and limitations # under the License. +import fixtures +from multiprocessing import Process +import time + from oslo_config import cfg from neutron._i18n import _ @@ -76,3 +80,53 @@ class KeepalivedManagerTestCase(base.BaseTestCase, def test_keepalived_respawn_with_unexpected_exit(self): self._test_keepalived_respawns(False) + + def _test_keepalived_spawns_conflicting_pid(self, process, pid_file): + # Test the situation when keepalived PID file contains PID of an + # existing non-keepalived process. This situation can happen e.g. + # after hard node reset. + + spawn_process = SleepyProcessFixture() + self.useFixture(spawn_process) + + with open(pid_file, "w") as f_pid_file: + f_pid_file.write("%s" % spawn_process.pid) + + self.manager.spawn() + utils.wait_until_true( + lambda: process.active, + timeout=5, + sleep=0.1, + exception=RuntimeError(_("Keepalived didn't spawn"))) + + def test_keepalived_spawns_conflicting_pid_base_process(self): + process = self.manager.get_process() + pid_file = process.get_pid_file_name() + self._test_keepalived_spawns_conflicting_pid(process, pid_file) + + def test_keepalived_spawns_conflicting_pid_vrrp_subprocess(self): + process = self.manager.get_process() + pid_file = process.get_pid_file_name() + self._test_keepalived_spawns_conflicting_pid( + process, + self.manager.get_vrrp_pid_file_name(pid_file)) + + +class SleepyProcessFixture(fixtures.Fixture): + + def __init__(self): + super(SleepyProcessFixture, self).__init__() + + @staticmethod + def yawn(): + time.sleep(60) + + def _setUp(self): + self.process = Process(target=self.yawn) + + def destroy(self): + self.process.terminate() + + @property + def pid(self): + return self.process.pid From 844cae4960cb2e3aedad750ceb91aa675f8e1142 Mon Sep 17 00:00:00 2001 From: Dmitry Sutyagin Date: Fri, 12 Feb 2016 12:18:14 +0300 Subject: [PATCH 25/51] Switches metering agent to stateless iptables If state_less parameter is not specified then neutron-postrouting-bottom rule goes up in POSTROUTING chain, which causes premature NATing of traffic, for ex. traffic between internal networks becomes NATed. Closes-Bug: 1544508 Co-Authored-By: Sergey Belous Change-Id: I2e0011237d50a59d417cfee01dcd5f9d0da2e7f5 (cherry picked from commit 5d2d1120fcdcd5977d3c760ac1520a841048d456) --- .../metering/drivers/iptables/iptables_driver.py | 1 + .../unit/services/metering/drivers/test_iptables.py | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/neutron/services/metering/drivers/iptables/iptables_driver.py b/neutron/services/metering/drivers/iptables/iptables_driver.py index 7a8c8fd0a8c..5c2c080f094 100644 --- a/neutron/services/metering/drivers/iptables/iptables_driver.py +++ b/neutron/services/metering/drivers/iptables/iptables_driver.py @@ -73,6 +73,7 @@ class RouterWithMetering(object): self.iptables_manager = iptables_manager.IptablesManager( namespace=self.ns_name, binary_name=WRAP_NAME, + state_less=True, use_ipv6=ipv6_utils.is_enabled()) self.metering_labels = {} diff --git a/neutron/tests/unit/services/metering/drivers/test_iptables.py b/neutron/tests/unit/services/metering/drivers/test_iptables.py index 91858e46417..a33a18b2880 100644 --- a/neutron/tests/unit/services/metering/drivers/test_iptables.py +++ b/neutron/tests/unit/services/metering/drivers/test_iptables.py @@ -106,6 +106,15 @@ class IptablesDriverTestCase(base.BaseTestCase): self.metering = iptables_driver.IptablesMeteringDriver('metering', cfg.CONF) + def test_create_stateless_iptables_manager(self): + routers = TEST_ROUTERS[:1] + self.metering.add_metering_label(None, routers) + self.iptables_cls.assert_called_with( + binary_name=mock.ANY, + namespace=mock.ANY, + state_less=True, + use_ipv6=mock.ANY) + def test_add_metering_label(self): routers = TEST_ROUTERS[:1] From 04fb1476de3b9d81ad579586c7010b5cdd2248a2 Mon Sep 17 00:00:00 2001 From: Hynek Mlnarik Date: Wed, 30 Mar 2016 10:44:09 +0200 Subject: [PATCH 26/51] Refactor and fix dummy process fixture Extracting the test fixture that creates a new process and leaves it running for a given amount of time into helpers where other fixtures for functional tests live. This both keeps the fixtures at one place and increases visibility of the fixture so that it can be reused in other tests. At the same time, the fixture is fixed as the original code omitted starting the process. Change-Id: I97aeb8d1d5773ef3d59e8f908aea34ccceb38378 Related-Bug: 1561046 (cherry picked from commit 2690eed19a749fb1b50bb38f3d01fce0f1497f39) --- .../tests/functional/agent/linux/helpers.py | 29 +++++++++++++++++++ .../functional/agent/linux/test_keepalived.py | 27 ++--------------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/neutron/tests/functional/agent/linux/helpers.py b/neutron/tests/functional/agent/linux/helpers.py index 4cd40f5a35f..3f7a288e1b5 100644 --- a/neutron/tests/functional/agent/linux/helpers.py +++ b/neutron/tests/functional/agent/linux/helpers.py @@ -12,7 +12,9 @@ # 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 multiprocessing import os +import time import fixtures @@ -56,3 +58,30 @@ class AdminDirFixture(fixtures.Fixture): delete_cmd = ['rm', '-r', self.directory] utils.execute(create_cmd, run_as_root=True) self.addCleanup(utils.execute, delete_cmd, run_as_root=True) + + +class SleepyProcessFixture(fixtures.Fixture): + """ + Process fixture that performs time.sleep for the given number of seconds. + """ + + def __init__(self, timeout=60): + super(SleepyProcessFixture, self).__init__() + self.timeout = timeout + + @staticmethod + def yawn(seconds): + time.sleep(seconds) + + def _setUp(self): + self.process = multiprocessing.Process(target=self.yawn, + args=[self.timeout]) + self.process.start() + self.addCleanup(self.destroy) + + def destroy(self): + self.process.terminate() + + @property + def pid(self): + return self.process.pid diff --git a/neutron/tests/functional/agent/linux/test_keepalived.py b/neutron/tests/functional/agent/linux/test_keepalived.py index ac1fe80cc92..e1110733a8b 100644 --- a/neutron/tests/functional/agent/linux/test_keepalived.py +++ b/neutron/tests/functional/agent/linux/test_keepalived.py @@ -13,10 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import fixtures -from multiprocessing import Process -import time - from oslo_config import cfg from neutron._i18n import _ @@ -24,6 +20,7 @@ from neutron.agent.linux import external_process from neutron.agent.linux import keepalived from neutron.agent.linux import utils from neutron.tests import base +from neutron.tests.functional.agent.linux import helpers from neutron.tests.unit.agent.linux import test_keepalived @@ -86,7 +83,7 @@ class KeepalivedManagerTestCase(base.BaseTestCase, # existing non-keepalived process. This situation can happen e.g. # after hard node reset. - spawn_process = SleepyProcessFixture() + spawn_process = helpers.SleepyProcessFixture() self.useFixture(spawn_process) with open(pid_file, "w") as f_pid_file: @@ -110,23 +107,3 @@ class KeepalivedManagerTestCase(base.BaseTestCase, self._test_keepalived_spawns_conflicting_pid( process, self.manager.get_vrrp_pid_file_name(pid_file)) - - -class SleepyProcessFixture(fixtures.Fixture): - - def __init__(self): - super(SleepyProcessFixture, self).__init__() - - @staticmethod - def yawn(): - time.sleep(60) - - def _setUp(self): - self.process = Process(target=self.yawn) - - def destroy(self): - self.process.terminate() - - @property - def pid(self): - return self.process.pid From 9679285f547b301a511e02ebc763b5406fb03ffc Mon Sep 17 00:00:00 2001 From: Jamie Lennox Date: Tue, 15 Mar 2016 10:05:29 +1100 Subject: [PATCH 27/51] Return oslo_config Opts to config generator We shouldn't be returning keystoneauth Opts to the oslo_config generator. Whilst it mostly works these objects are not interchangable and it can result in problems. You can see this by entries such as: # Warning: Failed to format sample for tenant_name # isinstance() arg 2 must be a class, type, or tuple of classes and types in the currently generated config files. Keystoneauth provides a function that returns oslo_config options so fetch, process and return those instead. Change-Id: Ie3fad2381467b19189cbb332c41cea8b6cf6e264 Closes-Bug: #1548433 (cherry picked from commit c3db0707eff70f381913643891ba4e148977407d) --- neutron/opts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neutron/opts.py b/neutron/opts.py index 41668119cdb..23e47962b7c 100644 --- a/neutron/opts.py +++ b/neutron/opts.py @@ -295,7 +295,7 @@ def list_auth_opts(): # the config options for a few common ones plugins = ['password', 'v2password', 'v3password'] for name in plugins: - for plugin_option in ks_loading.get_plugin_loader(name).get_options(): + for plugin_option in ks_loading.get_auth_plugin_conf_options(name): if all(option.name != plugin_option.name for option in opt_list): opt_list.append(plugin_option) opt_list.sort(key=operator.attrgetter('name')) From 3190494c0dfc9762d874399276327f096ce4bd92 Mon Sep 17 00:00:00 2001 From: Armando Migliaccio Date: Fri, 1 Apr 2016 13:38:06 -0700 Subject: [PATCH 28/51] Fix zuul_cloner errors during tox job setup Since [1], Tempest is a pip installable package, and that prevents zuul_cloner to work correctly. This change moves away from the existing logic in tox_install, and adds tempest as an explicit requirement for the api job. This is in fact the only tox target that needs Tempest to work. tox_install.sh has become less important now, but cleanup is left as follow up, to speed up gate salvation. [1] I25eac915c977ebaedced66ac896c5dd77259d193 Change-Id: I00d882dde77a687ecb57ec200a34fd96256ad87a (cherry picked from commit 8a6913c534e39e93640ed99c67e66763a9d1da3c) --- neutron/tests/api/requirements.txt | 7 +++++++ tools/tox_install.sh | 20 +------------------- tox.ini | 3 +++ 3 files changed, 11 insertions(+), 19 deletions(-) create mode 100644 neutron/tests/api/requirements.txt diff --git a/neutron/tests/api/requirements.txt b/neutron/tests/api/requirements.txt new file mode 100644 index 00000000000..6aae510d74d --- /dev/null +++ b/neutron/tests/api/requirements.txt @@ -0,0 +1,7 @@ +# Additional requirements for api tests + +# The order of packages is significant, because pip processes them in the order +# of appearance. Changing the order has an impact on the overall integration +# process, which may cause wedges in the gate later. + +tempest>=10.0.0 # Apache-2.0 diff --git a/tools/tox_install.sh b/tools/tox_install.sh index 70357748b97..32145ed28e8 100755 --- a/tools/tox_install.sh +++ b/tools/tox_install.sh @@ -9,10 +9,7 @@ # from neutron master via a hard-coded URL. That last case should only # happen with devs running unit tests locally. -ZUUL_CLONER=/usr/zuul-env/bin/zuul-cloner -tempest_installed=$(python -c "import tempest" 2>/dev/null ; echo $?) - -set -e +set -eux install_cmd="pip install" @@ -23,19 +20,4 @@ if [ "$CONSTRAINTS_FILE" != "unconstrained" ]; then install_cmd="$install_cmd -c$CONSTRAINTS_FILE" fi -if [ $tempest_installed -eq 0 ]; then - echo "Tempest already installed; using existing package" -elif [ -x "$ZUUL_CLONER" ]; then - export ZUUL_BRANCH=${ZUUL_BRANCH-$BRANCH} - pushd /tmp - $ZUUL_CLONER --cache-dir \ - /opt/git \ - git://git.openstack.org \ - openstack/tempest - $install_cmd -e openstack/tempest - popd -else - $install_cmd -U -egit+https://git.openstack.org/openstack/tempest#egg=tempest -fi - $install_cmd -U $* diff --git a/tox.ini b/tox.ini index cc7b975cbab..50a0fd338d5 100644 --- a/tox.ini +++ b/tox.ini @@ -24,6 +24,9 @@ setenv = {[testenv]setenv} OS_TEST_PATH=./neutron/tests/api TEMPEST_CONFIG_DIR={env:TEMPEST_CONFIG_DIR:/opt/stack/tempest/etc} OS_TEST_API_WITH_REST=1 +deps = + {[testenv]deps} + -r{toxinidir}/neutron/tests/api/requirements.txt [testenv:common] # Fake job to define environment variables shared between dsvm/non-dsvm jobs From 77696d8529c7310e343722d809ab2e63bd8946f9 Mon Sep 17 00:00:00 2001 From: OpenStack Proposal Bot Date: Fri, 8 Apr 2016 06:36:58 +0000 Subject: [PATCH 29/51] Imported Translations from Zanata For more information about this automatic import see: https://wiki.openstack.org/wiki/Translations/Infrastructure Change-Id: I2f2ef73e04e007e9b450d51a72ee60e1ec788518 --- .../ko_KR/LC_MESSAGES/neutron-log-warning.po | 47 +++++++++---------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-warning.po b/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-warning.po index 920f4b5de93..673bf585a47 100644 --- a/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-warning.po +++ b/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-warning.po @@ -3,17 +3,16 @@ # This file is distributed under the same license as the neutron project. # # Translators: -# OpenStack Infra , 2015. #zanata -# SeYeon Lee , 2016. #zanata +# Sungjin Kang , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0rc3.dev4\n" +"Project-Id-Version: neutron 8.0.1.dev1\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-29 10:14+0000\n" +"POT-Creation-Date: 2016-04-07 10:58+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-03-29 03:30+0000\n" +"PO-Revision-Date: 2016-04-07 07:06+0000\n" "Last-Translator: SeYeon Lee \n" "Language: ko-KR\n" "Plural-Forms: nplurals=1; plural=0;\n" @@ -95,7 +94,7 @@ msgstr "BgpDrAgent %s이(가) 작동 중지됨" #, python-format msgid "Cannot find vf index for pci slot %s" -msgstr "pci 슬롯 %s의 vf 인덱스를 찾을 수 없음" +msgstr "PCI 슬롯 %s에대한 vf 인덱스를 찾을 수 없음" #, python-format msgid "Cannot find vfs %(vfs)s in device %(dev_name)s" @@ -170,8 +169,8 @@ msgid "" "Dictionary %(dict_name)s for agent %(agent_type)s on host %(host)s is " "invalid." msgstr "" -"호스트 %(host)s에 있는 에이전트 %(agent_type)s의 사전 %(dict_name)s이(가) 올" -"바르지 않습니다." +"호스트 %(host)s에 있는 에이전트 %(agent_type)s 사전 %(dict_name)s이(가) 올바" +"르지 않습니다." #, python-format msgid "Did not find expected name \"%(ext_name)s\" in %(file)s" @@ -251,7 +250,7 @@ msgstr "아직 준비되지 않은 openvswitch 포트 발견: %s" #, python-format msgid "Info for router %s was not found. Performing router cleanup" -msgstr "라우터 %s의 정보를 찾지 못했습니다. 라우터 정리 수행" +msgstr "라우터 %s 정보를 찾지 못했습니다. 라우터 정리 수행" msgid "Invalid Interface ID, will lead to incorrect tap device name" msgstr "" @@ -322,7 +321,7 @@ msgstr "활성 L3 에이전트가 없음" #, python-format msgid "No controller found for: %s - returning response code 404" -msgstr "%s의 컨트롤러를 찾을 수 없음 - 응답 코드 404 리턴" +msgstr "%s 컨트롤러를 찾을 수 없음 - 응답 코드 404 반환됨" #, python-format msgid "No flat network found on physical network %s" @@ -335,12 +334,12 @@ msgstr "추가 DHCP 에이전트가 없음" msgid "" "No plugin found for resource:%s. API calls may not be correctly dispatched" msgstr "" -"%s 자원의 플러그인을 찾을 수 없습니다. API 호출이 올바르게 디스패치되지 않을 " +"%s 자원 플러그인을 찾을 수 없습니다. API 호출이 올바르게 디스패치되지 않을 " "수 있습니다." #, python-format msgid "No plugin found for: %s" -msgstr "%s의 플러그인을 찾을 수 없음" +msgstr "%s 플러그인을 찾을 수 없음" #, python-format msgid "No routers compatible with L3 agent configuration on host %s" @@ -348,7 +347,7 @@ msgstr "호스트 %s에서 L3 에이전트 구성과 호환 가능한 라우터 #, python-format msgid "No sqlalchemy event for resource %s found" -msgstr "자원 %s의 sqlalchemy 이벤트를 찾을 수 없음" +msgstr "자원 %s sqlalchemy 이벤트를 찾을 수 없음" #, python-format msgid "No valid gateway port on subnet %s is found for IPv6 RA" @@ -434,7 +433,7 @@ msgstr "" #, python-format msgid "Respawning %(service)s for uuid %(uuid)s" -msgstr "uuid %(uuid)s의 %(service)s 다시 파생" +msgstr "uuid %(uuid)s %(service)s 다시 파생" #, python-format msgid "Router %s was not found. Skipping agent notification." @@ -459,7 +458,7 @@ msgstr "" msgid "" "The input changed_since must be in the following format: YYYY-MM-DDTHH:MM:SS" -msgstr "input changed_since의 형식은 YYYY-MM-DDTHH:MM:SS이어야 함" +msgstr "input changed_since 형식은 YYYY-MM-DDTHH:MM:SS이어야 함" msgid "" "The quota driver neutron.quota.ConfDriver is deprecated as of Liberty. " @@ -480,7 +479,7 @@ msgid "" "root_helper. Disable the use_helper_for_ns_read option to avoid a " "performance impact." msgstr "" -"neutron을 실행하는 사용자가 root_helper를 사용하지 않고 네임스페이스를 읽을 " +"Neutron을 실행하는 사용자가 root_helper를 사용하지 않고 네임스페이스를 읽을 " "수 있습니다. 성능에 영향을 미치지 않도록 use_helper_for_ns_read 옵션을 사용하" "지 않게 설정하십시오." @@ -508,16 +507,16 @@ msgid "" "current state; please check that the network and/or its subnet(s) still " "exist." msgstr "" -"%(net_id)s의 dhcp에 대해 %(action)s을(를) 수행할 수 없음: 현재 상태와 충돌됩" -"니다. 네트워크 및/또는 서브넷이 여전히 있는지 확인하십시오." +"%(net_id)s dhcp에 대해 %(action)s을(를) 수행할 수 없음: 현재 상태와 충돌됩니" +"다. 네트워크 및/또는 서브넷이 여전히 있는지 확인하십시오." #, python-format msgid "Unable to configure IP address for floating IP: %s" -msgstr "Floating IP의 IP 주소를 구성할 수 없음: %s" +msgstr "Floating IP에대한 IP 주소를 구성할 수 없음: %s" #, python-format msgid "Unable to find data type descriptor for attribute %s" -msgstr "속성 %s의 데이터 유형 설명자를 찾을 수 없음" +msgstr "속성 %s 데이터 유형 descriptor를 찾을 수 없음" #, python-format msgid "Unable to retrieve active L2 agent on host %s" @@ -533,7 +532,7 @@ msgstr "" #, python-format msgid "Unsupported QoS rule type for %(rule_id)s: %(rule_type)s; skipping" -msgstr "%(rule_id)s의 지원되지 않는 QoS 규칙 유형: %(rule_type)s. 건너뜁니다." +msgstr "%(rule_id)s 지원되지 않는 QoS 규칙 유형: %(rule_type)s. 건너뜁니다." #, python-format msgid "Updating lease expiration is now deprecated. Issued from host %s." @@ -570,7 +569,7 @@ msgstr "" #, python-format msgid "device pci mismatch: %(device_mac)s - %(pci_slot)s" -msgstr "장치 pci 불일치: %(device_mac)s - %(pci_slot)s" +msgstr "장치 PCI 불일치: %(device_mac)s - %(pci_slot)s" #, python-format msgid "failed to parse vf link show line %(line)s: for %(device)s" @@ -598,7 +597,7 @@ msgstr "" #, python-format msgid "ofport: %(ofport)s for VIF: %(vif)s is not a positive integer" -msgstr "VIF: %(vif)s의 fport: %(ofport)s이(가) 양수가 아님" +msgstr "VIF: %(vif)s fport: %(ofport)s이(가) 양수가 아님" #, python-format msgid "port_id to device with MAC %s not found" @@ -613,4 +612,4 @@ msgstr "" #, python-format msgid "unable to modify mac_address of ACTIVE port %s" -msgstr "활성 포트 %s의 mac_address를 수정할 수 없음" +msgstr "활성 포트 %s에대한 mac_address를 수정할 수 없음" From ee32ea5e2bf2b01104c5bde6b6a5018dd0e15f57 Mon Sep 17 00:00:00 2001 From: Ihar Hrachyshka Date: Thu, 7 Apr 2016 19:15:01 +0200 Subject: [PATCH 30/51] Switched from fixtures to mock to mock out starting RPC consumers fixtures 2.0.0 broke us wildly, so instead of trying to make it work with new fixtures, I better just switch the mock to... mock. Change-Id: I58d7a750e263e4af54589ace07ac00bec34b553a Closes-Bug: #1567295 (cherry picked from commit 2af86b8f6f749bf7b42a2c04b48c9a2dc28a46c9) --- neutron/tests/base.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/neutron/tests/base.py b/neutron/tests/base.py index 2f5d57e860f..a303ed2479f 100644 --- a/neutron/tests/base.py +++ b/neutron/tests/base.py @@ -66,10 +66,6 @@ def fake_use_fatal_exceptions(*args): return True -def fake_consume_in_threads(self): - return [] - - def get_rand_name(max_length=None, prefix='test'): """Return a random string. @@ -318,9 +314,9 @@ class BaseTestCase(DietTestCase): def setup_rpc_mocks(self): # don't actually start RPC listeners when testing - self.useFixture(fixtures.MonkeyPatch( + mock.patch( 'neutron.common.rpc.Connection.consume_in_threads', - fake_consume_in_threads)) + return_value=[]).start() self.useFixture(fixtures.MonkeyPatch( 'oslo_messaging.Notifier', fake_notifier.FakeNotifier)) From c178bd9565ae699a79a8f13e89d1f8717a765cc1 Mon Sep 17 00:00:00 2001 From: Armando Migliaccio Date: Wed, 30 Mar 2016 14:24:58 -0700 Subject: [PATCH 31/51] Fix race conditions in IP availability API tests DHCP port creation is asynchronous with subnet creation. Therefore there is a time window where, depending on how fast the DHCP agent honors the request, the DHCP port IP allocation may or may not be accounted for in the total number of used IP for the network. To kill the race, do not run dhcp on the created subnets at all. Closes-bug: 1563883 Change-Id: Idda25e65d04852d68a3c160cc9deefdb4ee82dcd (cherry picked from commit 27634bb2ba2637d694c7d0aa5758173d12ef579a) --- neutron/tests/api/test_network_ip_availability.py | 1 + 1 file changed, 1 insertion(+) diff --git a/neutron/tests/api/test_network_ip_availability.py b/neutron/tests/api/test_network_ip_availability.py index 580916b9979..5569311eda4 100644 --- a/neutron/tests/api/test_network_ip_availability.py +++ b/neutron/tests/api/test_network_ip_availability.py @@ -90,6 +90,7 @@ class NetworksIpAvailabilityTest(base.BaseAdminNetworkTest): prefix_len = subnet_cidr.prefixlen subnet = self.create_subnet(network, cidr=subnet_cidr, + enable_dhcp=False, mask_bits=mask_bits, ip_version=ip_version) return subnet, prefix_len From 5853af9cba6733725d6c9ac0db644f426713f0cf Mon Sep 17 00:00:00 2001 From: Dustin Lundquist Date: Thu, 31 Mar 2016 12:04:31 -0700 Subject: [PATCH 32/51] Iptables firewall prevent IP spoofed DHCP requests The DHCP rules in the fixed iptables firewall rules were too permissive. They permitted any UDP traffic with a source port of 68 and destination port of 67. Care must be taken since these rules return before the IP spoofing prevention rules. This patch splits the fixed DHCP rules into two, one for the discovery and request messages which take place before the instance has bound an IP address and a second to permit DHCP renewals. Change-Id: Ibc2b0fa80baf2ea8b01fa568cd1fe7a7e092e7a5 Partial-Bug: #1558658 (cherry picked from commit 6a93ee8ac1a901c255e3475a24f1afc11d8bf80f) --- neutron/agent/linux/iptables_firewall.py | 9 +- .../tests/functional/agent/test_firewall.py | 3 + .../agent/linux/test_iptables_firewall.py | 42 +++- .../unit/agent/test_securitygroups_rpc.py | 187 ++++++++++-------- 4 files changed, 149 insertions(+), 92 deletions(-) diff --git a/neutron/agent/linux/iptables_firewall.py b/neutron/agent/linux/iptables_firewall.py index 36a1feccb0f..afc815255a9 100644 --- a/neutron/agent/linux/iptables_firewall.py +++ b/neutron/agent/linux/iptables_firewall.py @@ -381,9 +381,9 @@ class IptablesFirewallDriver(firewall.FirewallDriver): mac_ipv6_pairs.append((mac, ip_address)) def _spoofing_rule(self, port, ipv4_rules, ipv6_rules): - # Allow dhcp client packets - ipv4_rules += [comment_rule('-p udp -m udp --sport 68 ' - '-m udp --dport 67 ' + # Allow dhcp client discovery and request + ipv4_rules += [comment_rule('-s 0.0.0.0/32 -d 255.255.255.255/32 ' + '-p udp -m udp --sport 68 --dport 67 ' '-j RETURN', comment=ic.DHCP_CLIENT)] # Drop Router Advts from the port. ipv6_rules += [comment_rule('-p ipv6-icmp -m icmp6 --icmpv6-type %s ' @@ -415,6 +415,9 @@ class IptablesFirewallDriver(firewall.FirewallDriver): mac_ipv4_pairs, ipv4_rules) self._setup_spoof_filter_chain(port, self.iptables.ipv6['filter'], mac_ipv6_pairs, ipv6_rules) + # Allow dhcp client renewal and rebinding + ipv4_rules += [comment_rule('-p udp -m udp --sport 68 --dport 67 ' + '-j RETURN', comment=ic.DHCP_CLIENT)] def _drop_dhcp_rule(self, ipv4_rules, ipv6_rules): #Note(nati) Drop dhcp packet from VM diff --git a/neutron/tests/functional/agent/test_firewall.py b/neutron/tests/functional/agent/test_firewall.py index 1104e286931..f189f59685c 100644 --- a/neutron/tests/functional/agent/test_firewall.py +++ b/neutron/tests/functional/agent/test_firewall.py @@ -355,6 +355,9 @@ class FirewallTestCase(BaseFirewallTestCase): direction=self.tester.INGRESS) self.tester.assert_no_connection(protocol=self.tester.ICMP, direction=self.tester.EGRESS) + self.tester.assert_no_connection(protocol=self.tester.UDP, + src_port=68, dst_port=67, + direction=self.tester.EGRESS) @skip_if_firewall('openvswitch') def test_ip_spoofing_works_without_port_security_enabled(self): diff --git a/neutron/tests/unit/agent/linux/test_iptables_firewall.py b/neutron/tests/unit/agent/linux/test_iptables_firewall.py index cdc9b6151aa..36f61e86c48 100644 --- a/neutron/tests/unit/agent/linux/test_iptables_firewall.py +++ b/neutron/tests/unit/agent/linux/test_iptables_firewall.py @@ -158,10 +158,15 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp ' + '--sport 68 --dport 67 -j RETURN', comment=None), mock.call.add_rule('ofake_dev', '-j $sfake_dev', comment=None), + mock.call.add_rule( + 'ofake_dev', + '-p udp -m udp --sport 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -940,7 +945,8 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): filter_inst = self.v4filter_inst dhcp_rule = [mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp ' + '--sport 68 --dport 67 -j RETURN', comment=None)] if ethertype == 'IPv6': @@ -1027,6 +1033,10 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): calls.append(mock.call.add_rule('ofake_dev', '-j $sfake_dev', comment=None)) if ethertype == 'IPv4': + calls.append(mock.call.add_rule( + 'ofake_dev', + '-p udp -m udp --sport 68 --dport 67 -j RETURN', + comment=None)) calls.append(mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -1195,10 +1205,15 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp ' + '--sport 68 --dport 67 -j RETURN', comment=None), mock.call.add_rule('ofake_dev', '-j $sfake_dev', comment=None), + mock.call.add_rule( + 'ofake_dev', + '-p udp -m udp --sport 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -1267,10 +1282,15 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp ' + '--sport 68 --dport 67 -j RETURN', comment=None), mock.call.add_rule('ofake_dev', '-j $sfake_dev', comment=None), + mock.call.add_rule( + 'ofake_dev', + '-p udp -m udp --sport 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -1442,10 +1462,15 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp ' + '--sport 68 --dport 67 -j RETURN', comment=None), mock.call.add_rule('ofake_dev', '-j $sfake_dev', comment=None), + mock.call.add_rule( + 'ofake_dev', + '-p udp -m udp --sport 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', @@ -1516,10 +1541,15 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase): comment=ic.PAIR_DROP), mock.call.add_rule( 'ofake_dev', - '-p udp -m udp --sport 68 -m udp --dport 67 -j RETURN', + '-s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp ' + '--sport 68 --dport 67 -j RETURN', comment=None), mock.call.add_rule('ofake_dev', '-j $sfake_dev', comment=None), + mock.call.add_rule( + 'ofake_dev', + '-p udp -m udp --sport 68 --dport 67 -j RETURN', + comment=None), mock.call.add_rule( 'ofake_dev', '-p udp -m udp --sport 67 -m udp --dport 68 -j DROP', diff --git a/neutron/tests/unit/agent/test_securitygroups_rpc.py b/neutron/tests/unit/agent/test_securitygroups_rpc.py index dd5a5607c1a..3cdc1abadf0 100644 --- a/neutron/tests/unit/agent/test_securitygroups_rpc.py +++ b/neutron/tests/unit/agent/test_securitygroups_rpc.py @@ -1888,14 +1888,15 @@ IPSET_FILTER_1 = """# Generated by iptables_manager RETURN -I %(bn)s-i_port1 5 -m state --state INVALID -j DROP -I %(bn)s-i_port1 6 -j %(bn)s-sg-fallback --I %(bn)s-o_port1 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_port1 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_port1 2 -j %(bn)s-s_port1 --I %(bn)s-o_port1 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_port1 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_port1 5 -j RETURN --I %(bn)s-o_port1 6 -m state --state INVALID -j DROP --I %(bn)s-o_port1 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_port1 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_port1 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_port1 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_port1 6 -j RETURN +-I %(bn)s-o_port1 7 -m state --state INVALID -j DROP +-I %(bn)s-o_port1 8 -j %(bn)s-sg-fallback -I %(bn)s-s_port1 1 -s 10.0.0.3/32 -m mac --mac-source 12:34:56:78:9A:BC \ -j RETURN -I %(bn)s-s_port1 2 -j DROP @@ -1944,14 +1945,15 @@ IPTABLES_FILTER_1 = """# Generated by iptables_manager -I %(bn)s-i_port1 3 -p tcp -m tcp --dport 22 -j RETURN -I %(bn)s-i_port1 4 -m state --state INVALID -j DROP -I %(bn)s-i_port1 5 -j %(bn)s-sg-fallback --I %(bn)s-o_port1 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_port1 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_port1 2 -j %(bn)s-s_port1 --I %(bn)s-o_port1 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_port1 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_port1 5 -j RETURN --I %(bn)s-o_port1 6 -m state --state INVALID -j DROP --I %(bn)s-o_port1 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_port1 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_port1 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_port1 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_port1 6 -j RETURN +-I %(bn)s-o_port1 7 -m state --state INVALID -j DROP +-I %(bn)s-o_port1 8 -j %(bn)s-sg-fallback -I %(bn)s-s_port1 1 -s 10.0.0.3/32 -m mac --mac-source 12:34:56:78:9A:BC \ -j RETURN -I %(bn)s-s_port1 2 -j DROP @@ -2002,14 +2004,15 @@ IPTABLES_FILTER_1_2 = """# Generated by iptables_manager -I %(bn)s-i_port1 4 -s 10.0.0.4/32 -j RETURN -I %(bn)s-i_port1 5 -m state --state INVALID -j DROP -I %(bn)s-i_port1 6 -j %(bn)s-sg-fallback --I %(bn)s-o_port1 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_port1 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_port1 2 -j %(bn)s-s_port1 --I %(bn)s-o_port1 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_port1 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_port1 5 -j RETURN --I %(bn)s-o_port1 6 -m state --state INVALID -j DROP --I %(bn)s-o_port1 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_port1 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_port1 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_port1 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_port1 6 -j RETURN +-I %(bn)s-o_port1 7 -m state --state INVALID -j DROP +-I %(bn)s-o_port1 8 -j %(bn)s-sg-fallback -I %(bn)s-s_port1 1 -s 10.0.0.3/32 -m mac --mac-source 12:34:56:78:9A:BC \ -j RETURN -I %(bn)s-s_port1 2 -j DROP @@ -2077,20 +2080,24 @@ IPSET_FILTER_2 = """# Generated by iptables_manager -I %(bn)s-i_%(port2)s 4 -m set --match-set NIPv4security_group1 src -j RETURN -I %(bn)s-i_%(port2)s 5 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 6 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN @@ -2163,20 +2170,24 @@ IPSET_FILTER_2_3 = """# Generated by iptables_manager -I %(bn)s-i_%(port2)s 5 -p icmp -j RETURN -I %(bn)s-i_%(port2)s 6 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN @@ -2247,22 +2258,24 @@ IPTABLES_FILTER_2 = """# Generated by iptables_manager -I %(bn)s-i_%(port2)s 4 -s %(ip1)s -j RETURN -I %(bn)s-i_%(port2)s 5 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 6 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 \ --j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN @@ -2332,20 +2345,24 @@ IPTABLES_FILTER_2_2 = """# Generated by iptables_manager -I %(bn)s-i_%(port2)s 4 -s %(ip1)s -j RETURN -I %(bn)s-i_%(port2)s 5 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 6 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN @@ -2418,20 +2435,24 @@ IPTABLES_FILTER_2_3 = """# Generated by iptables_manager -I %(bn)s-i_%(port2)s 5 -p icmp -j RETURN -I %(bn)s-i_%(port2)s 6 -m state --state INVALID -j DROP -I %(bn)s-i_%(port2)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port1)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port1)s 2 -j %(bn)s-s_%(port1)s --I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port1)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port1)s 5 -j RETURN --I %(bn)s-o_%(port1)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port1)s 7 -j %(bn)s-sg-fallback --I %(bn)s-o_%(port2)s 1 -p udp -m udp --sport 68 -m udp --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port1)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port1)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port1)s 6 -j RETURN +-I %(bn)s-o_%(port1)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port1)s 8 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 1 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp \ +--sport 68 --dport 67 -j RETURN -I %(bn)s-o_%(port2)s 2 -j %(bn)s-s_%(port2)s --I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP --I %(bn)s-o_%(port2)s 4 -m state --state RELATED,ESTABLISHED -j RETURN --I %(bn)s-o_%(port2)s 5 -j RETURN --I %(bn)s-o_%(port2)s 6 -m state --state INVALID -j DROP --I %(bn)s-o_%(port2)s 7 -j %(bn)s-sg-fallback +-I %(bn)s-o_%(port2)s 3 -p udp -m udp --sport 68 --dport 67 -j RETURN +-I %(bn)s-o_%(port2)s 4 -p udp -m udp --sport 67 -m udp --dport 68 -j DROP +-I %(bn)s-o_%(port2)s 5 -m state --state RELATED,ESTABLISHED -j RETURN +-I %(bn)s-o_%(port2)s 6 -j RETURN +-I %(bn)s-o_%(port2)s 7 -m state --state INVALID -j DROP +-I %(bn)s-o_%(port2)s 8 -j %(bn)s-sg-fallback -I %(bn)s-s_%(port1)s 1 -s %(ip1)s -m mac --mac-source %(mac1)s -j RETURN -I %(bn)s-s_%(port1)s 2 -j DROP -I %(bn)s-s_%(port2)s 1 -s %(ip2)s -m mac --mac-source %(mac2)s -j RETURN From fa5eb530bb71c1b1fe1020802a63b05907695011 Mon Sep 17 00:00:00 2001 From: Kevin Benton Date: Wed, 16 Mar 2016 01:35:26 -0700 Subject: [PATCH 33/51] Add uselist=True to subnet rbac_entries relationship Because the join conditions for Subnet rbac entries are manually specified, SQLAlchemy is not automatically detecting that this relationship is a list. This adds the uselist=True kwarg to the relationship to ensure that it's always handled as a list. Change-Id: Ia4ae57ddd932260691584ae74c0305a79b2e60a9 Closes-Bug: #1557959 (cherry picked from commit 691f8f5ea54c04bfdfb76e25bda14665b05ed859) --- neutron/db/models_v2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neutron/db/models_v2.py b/neutron/db/models_v2.py index 7780c71e4f8..8a05ead1269 100644 --- a/neutron/db/models_v2.py +++ b/neutron/db/models_v2.py @@ -220,7 +220,7 @@ class Subnet(model_base.HasStandardAttributes, model_base.BASEV2, # subnets don't have their own rbac_entries, they just inherit from # the network rbac entries rbac_entries = orm.relationship( - rbac_db_models.NetworkRBAC, lazy='joined', + rbac_db_models.NetworkRBAC, lazy='joined', uselist=True, foreign_keys='Subnet.network_id', primaryjoin='Subnet.network_id==NetworkRBAC.object_id') From a2d1c46fe7952abc392d91ef3d00d203e0f38a4c Mon Sep 17 00:00:00 2001 From: Ihar Hrachyshka Date: Thu, 24 Mar 2016 16:16:17 +0100 Subject: [PATCH 34/51] firewall: don't warn about a driver that does not accept bridge Drivers that do not need the bridge parameter are safe to ignore it. Actually, the base abstract interface for those drivers does not allow to pass the new parameter. Ideally, the base class __init__ signature would change to accept the argument, but we can't do it without breaking API. So instead, just handle both types of drivers - those that accept the additional argument, and those that don't. And don't assume the latter are somehow wrong. Change-Id: Iceee46f63669b28e3a34d207216d864f1bfa5cf8 Closes-Bug: #1561243 (cherry picked from commit 193aa35325b897b960de88b510181b377e4c345c) --- neutron/agent/securitygroups_rpc.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/neutron/agent/securitygroups_rpc.py b/neutron/agent/securitygroups_rpc.py index 29909a1d140..8c5c1d932f4 100644 --- a/neutron/agent/securitygroups_rpc.py +++ b/neutron/agent/securitygroups_rpc.py @@ -103,12 +103,7 @@ class SecurityGroupAgentRpc(object): try: self.firewall = firewall_class( integration_bridge=integration_bridge) - except TypeError as e: - LOG.warning(_LW("Firewall driver %(fw_driver)s doesn't accept " - "integration_bridge parameter in __init__(): " - "%(err)s"), - {'fw_driver': firewall_driver, - 'err': e}) + except TypeError: self.firewall = firewall_class() # The following flag will be set to true if port filter must not be # applied as soon as a rule or membership notification is received From 681441137b8590620c6a1f35ab5931edb22d7a31 Mon Sep 17 00:00:00 2001 From: OpenStack Proposal Bot Date: Mon, 11 Apr 2016 06:27:57 +0000 Subject: [PATCH 35/51] Imported Translations from Zanata For more information about this automatic import see: https://wiki.openstack.org/wiki/Translations/Infrastructure Change-Id: Ia032d91e89bd78e16412b9bc7f60f466c61a16e5 --- neutron/locale/de/LC_MESSAGES/neutron.po | 7 +- neutron/locale/es/LC_MESSAGES/neutron.po | 7 +- neutron/locale/fr/LC_MESSAGES/neutron.po | 7 +- neutron/locale/it/LC_MESSAGES/neutron.po | 7 +- neutron/locale/ja/LC_MESSAGES/neutron.po | 7 +- .../ko_KR/LC_MESSAGES/neutron-log-error.po | 162 +++++++++--------- .../ko_KR/LC_MESSAGES/neutron-log-info.po | 43 +++-- neutron/locale/ko_KR/LC_MESSAGES/neutron.po | 61 ++++--- neutron/locale/neutron.pot | 76 ++++---- neutron/locale/pt_BR/LC_MESSAGES/neutron.po | 7 +- neutron/locale/ru/LC_MESSAGES/neutron.po | 7 +- neutron/locale/tr_TR/LC_MESSAGES/neutron.po | 7 +- neutron/locale/zh_CN/LC_MESSAGES/neutron.po | 7 +- neutron/locale/zh_TW/LC_MESSAGES/neutron.po | 7 +- 14 files changed, 186 insertions(+), 226 deletions(-) diff --git a/neutron/locale/de/LC_MESSAGES/neutron.po b/neutron/locale/de/LC_MESSAGES/neutron.po index 548b5bde508..53498bda3ae 100644 --- a/neutron/locale/de/LC_MESSAGES/neutron.po +++ b/neutron/locale/de/LC_MESSAGES/neutron.po @@ -7,9 +7,9 @@ # Frank Kloeker , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0rc2.dev16\n" +"Project-Id-Version: neutron 8.0.1.dev29\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-24 09:29+0000\n" +"POT-Creation-Date: 2016-04-10 14:30+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -3076,9 +3076,6 @@ msgstr "" "Portsicherheit muss aktiviert werden, damit zulässige Adresspaare für einen " "Port vorhanden sind." -msgid "Port does not have port security binding." -msgstr "Port verfügt nicht über Portsicherheitsbindung." - msgid "" "Port has security group associated. Cannot disable port security or ip " "address until security group is removed" diff --git a/neutron/locale/es/LC_MESSAGES/neutron.po b/neutron/locale/es/LC_MESSAGES/neutron.po index 56375be2969..ec7ea95304b 100644 --- a/neutron/locale/es/LC_MESSAGES/neutron.po +++ b/neutron/locale/es/LC_MESSAGES/neutron.po @@ -10,9 +10,9 @@ # Tom Cocozzello , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0rc3.dev4\n" +"Project-Id-Version: neutron 8.0.1.dev29\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-29 10:14+0000\n" +"POT-Creation-Date: 2016-04-10 14:30+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -3054,9 +3054,6 @@ msgstr "" "Seguridad de puerto debe habilitar para tener pares de dirección admitida en " "un puerto." -msgid "Port does not have port security binding." -msgstr "El puerto no tiene enlace de seguridad de puerto." - msgid "" "Port has security group associated. Cannot disable port security or ip " "address until security group is removed" diff --git a/neutron/locale/fr/LC_MESSAGES/neutron.po b/neutron/locale/fr/LC_MESSAGES/neutron.po index a3811ee5e5e..29269ebef28 100644 --- a/neutron/locale/fr/LC_MESSAGES/neutron.po +++ b/neutron/locale/fr/LC_MESSAGES/neutron.po @@ -16,9 +16,9 @@ # Tom Cocozzello , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0rc3.dev2\n" +"Project-Id-Version: neutron 8.0.1.dev29\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-25 15:59+0000\n" +"POT-Creation-Date: 2016-04-10 14:30+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -3073,9 +3073,6 @@ msgstr "" "La sécurité du port doit être activée pour avoir les paires d'adresse " "autorisées sur un port." -msgid "Port does not have port security binding." -msgstr "Le port ne comporte pas de liaison de sécurité." - msgid "" "Port has security group associated. Cannot disable port security or ip " "address until security group is removed" diff --git a/neutron/locale/it/LC_MESSAGES/neutron.po b/neutron/locale/it/LC_MESSAGES/neutron.po index 9a4aa14fbc7..15d121a8aea 100644 --- a/neutron/locale/it/LC_MESSAGES/neutron.po +++ b/neutron/locale/it/LC_MESSAGES/neutron.po @@ -9,9 +9,9 @@ # Tom Cocozzello , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0rc2.dev15\n" +"Project-Id-Version: neutron 8.0.1.dev29\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-24 00:54+0000\n" +"POT-Creation-Date: 2016-04-10 14:30+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -3008,9 +3008,6 @@ msgstr "" "Abilitare la sicurezza della porta per disporre di coppie di indirizzo " "consentite ad una porta." -msgid "Port does not have port security binding." -msgstr "La porta non dispone di un bind di sicurezza della porta." - msgid "" "Port has security group associated. Cannot disable port security or ip " "address until security group is removed" diff --git a/neutron/locale/ja/LC_MESSAGES/neutron.po b/neutron/locale/ja/LC_MESSAGES/neutron.po index 747c66b7c85..8d4c5363efb 100644 --- a/neutron/locale/ja/LC_MESSAGES/neutron.po +++ b/neutron/locale/ja/LC_MESSAGES/neutron.po @@ -18,9 +18,9 @@ # 笹原 昌美 , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0rc3.dev10\n" +"Project-Id-Version: neutron 8.0.1.dev29\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-31 01:13+0000\n" +"POT-Creation-Date: 2016-04-10 14:30+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -2974,9 +2974,6 @@ msgstr "" "ポートセキュリティーは、ポート上で許可されたアドレスペアを持つために有効にす" "る必要があります。" -msgid "Port does not have port security binding." -msgstr "ポートにポートセキュリティーバインディングがありません。" - msgid "" "Port has security group associated. Cannot disable port security or ip " "address until security group is removed" diff --git a/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-error.po b/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-error.po index 7d54501ef89..151503c6275 100644 --- a/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-error.po +++ b/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-error.po @@ -3,17 +3,16 @@ # This file is distributed under the same license as the neutron project. # # Translators: -# OpenStack Infra , 2015. #zanata -# SeYeon Lee , 2016. #zanata +# Sungjin Kang , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0rc3.dev4\n" +"Project-Id-Version: neutron 8.0.1.dev29\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-29 10:14+0000\n" +"POT-Creation-Date: 2016-04-10 14:30+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-03-29 11:43+0000\n" +"PO-Revision-Date: 2016-04-08 12:52+0000\n" "Last-Translator: SeYeon Lee \n" "Language: ko-KR\n" "Plural-Forms: nplurals=1; plural=0;\n" @@ -26,7 +25,7 @@ msgid "" "%(service)s for %(resource_type)s with uuid %(uuid)s not found. The process " "should not have died" msgstr "" -"uuid가 %(uuid)s인 %(resource_type)s의 %(service)s를 찾을 수 없습니다. 프로세" +"UUID가 %(uuid)s인 %(resource_type)s의 %(service)s를 찾을 수 없습니다. 프로세" "스가 종료되지 않았어야 합니다." #, python-format @@ -67,7 +66,7 @@ msgid "Agent Initialization Failed" msgstr "에이전트 초기화 실패" msgid "Alias or class name is not set" -msgstr "별명 또는 클래스 이름이 설정되지 않음" +msgstr "별명이나 클래스 이름이 설정되지 않음" #, python-format msgid "An error occurred while communicating with async process [%s]." @@ -102,11 +101,11 @@ msgid "BGP peer %(bgp_peer)s info call failed with reason=%(e)s." msgstr "BGP 피어 %(bgp_peer)s 정보 호출에 실패했으며, 이유=%(e)s입니다." msgid "BGP router-id MUST be specified for the correct functional working." -msgstr "기능적으로 올바르게 작동하도록 BGP 라우터-id를 지정해야 합니다." +msgstr "기능적으로 올바르게 작동하도록 BGP router-id를 지정해야 합니다." #, python-format msgid "Binding info for DVR port %s not found" -msgstr "DVR 포트 %s의 바인딩 정보를 찾을 수 없음" +msgstr "DVR 포트 %s에대한 바인딩 정보를 찾을 수 없음" #, python-format msgid "" @@ -120,7 +119,7 @@ msgstr "" msgid "" "Bridge %(brq)s for physical network %(net)s does not exist. Agent terminated!" msgstr "" -"실제 네트워크 %(net)s의 브릿지 %(brq)s이(가) 없습니다. 에이전트가 종료되었습" +"실제 네트워크 %(net)s에 브릿지 %(brq)s이(가) 없습니다. 에이전트가 종료되었습" "니다!" #, python-format @@ -128,7 +127,7 @@ msgid "" "Call to driver for BGP Speaker %(bgp_speaker)s %(method)s has failed with " "exception %(driver_exec)s." msgstr "" -"BGP 스피커 %(bgp_speaker)s %(method)s의 드라이버를 호출했지만 예외 " +"BGP 스피커 %(bgp_speaker)s %(method)s 드라이버를 호출했지만 예외 " "%(driver_exec)s이(가) 발생하며 실패했습니다." #, python-format @@ -175,20 +174,20 @@ msgstr "" "확보할 수 없음" msgid "Cannot run ebtables. Please ensure that it is installed." -msgstr "ebtables를 실행할 수 없습니다. 설치되었는지 확인하십시오." +msgstr "Ebtables를 실행할 수 없습니다. 설치되었는지 확인하십시오." msgid "Cannot run ip6tables. Please ensure that it is installed." -msgstr "ip6tables를 실행할 수 없습니다. 설치되었는지 확인하십시오." +msgstr "IP6tables를 실행할 수 없습니다. 설치되었는지 확인하십시오." msgid "Cannot run ipset. Please ensure that it is installed." -msgstr "ipset을 실행할 수 없습니다. 설치되었는지 확인하십시오." +msgstr "IPset을 실행할 수 없습니다. 설치되었는지 확인하십시오." #, python-format msgid "" "Centralized-SNAT port %(port)s on subnet %(port_subnet)s already seen on a " "different subnet %(orig_subnet)s" msgstr "" -"서브넷 %(port_subnet)s의 중앙 집중식 SNAT 포트 %(port)s이(가) 다른 서브넷 " +"서브넷 %(port_subnet)s 중앙 집중식 SNAT 포트 %(port)s이(가) 다른 서브넷 " "%(orig_subnet)s에 이미 표시됨" msgid "" @@ -252,14 +251,14 @@ msgid "" "Check for VF management support failed. Please ensure that the version of ip " "link being used has VF support." msgstr "" -"VF 관리 지원을 확인하는 데 실패했습니다. 사용 중인 ip 링크의 버전에 VF 지원" -"이 있는지 확인하십시오." +"VF 관리 지원을 확인하는 데 실패했습니다. 사용 중인 ip 링크 버전에 VF 지원이 " +"있는지 확인하십시오." msgid "" "Check for iproute2 VXLAN support failed. Please ensure that the iproute2 has " "VXLAN support." msgstr "" -"iproute2 VXLAN 지원을 확인하는 데 실패했습니다. iproute2에서 VXLAN을 지원하는" +"Iproute2 VXLAN 지원을 확인하는 데 실패했습니다. Iproute2에서 VXLAN을 지원하는" "지 확인하십시오." msgid "Check for native OVSDB support failed." @@ -267,7 +266,7 @@ msgstr "네이티브 OVSDB 지원을 확인하는 데 실패했습니다." #, python-format msgid "Configuration for devices %s failed!" -msgstr "장치 %s의 구성에 실패했습니다!" +msgstr "장치 %s 에대한 구성을 실패했습니다!" #, python-format msgid "Could not delete %(res)s %(id)s." @@ -283,7 +282,7 @@ msgstr "구문 분석할 수 없음: %(raw_result)s. 예외: %(exception)s" #, python-format msgid "Could not retrieve gateway port for subnet %s" -msgstr "서브넷 %s의 게이트웨이 포트를 검색할 수 없음" +msgstr "서브넷 %s에서 게이트웨이 포트를 검색할 수 없음" #, python-format msgid "DVR: Duplicate DVR router interface detected for subnet %s" @@ -300,8 +299,8 @@ msgid "" "DVR: SNAT port not found in the list %(snat_list)s for the given router " "internal port %(int_p)s" msgstr "" -"DVR: 지정된 라우터 내부 포트 %(int_p)s의 목록 %(snat_list)s에서 SNAT 포트를 " -"찾을 수 없음" +"DVR: 지정된 라우터 내부 포트 %(int_p)s 목록 %(snat_list)s에서 SNAT 포트를 찾" +"을 수 없음" msgid "DVR: error adding redirection logic" msgstr "DVR: 리디렉션 로직을 추가하는 중 오류 발생" @@ -346,7 +345,7 @@ msgstr "명령 실행 오류" #, python-format msgid "Error in agent loop. Devices info: %s" -msgstr "에이전트 루프에 오류 발생. 디바이스 정보: %s" +msgstr "에이전트 루프에서 오류 발생. 디바이스 정보: %s" msgid "Error loading class by alias" msgstr "별명으로 클래스를 로드하는 중 오류 발생" @@ -389,7 +388,7 @@ msgstr "[%(cmd)s]에서 오류 수신: %(err)s" #, python-format msgid "Error response returned from nova: %s" -msgstr "nova에서 오류 응답을 리턴함: %s" +msgstr "Nova에서 오류 응답을 반환함: %s" #, python-format msgid "Error unable to destroy namespace: %s" @@ -400,7 +399,7 @@ msgstr "터널 엔드포인트를 구성하는 중에 오류 발생" #, python-format msgid "Error while create dnsmasq log dir: %s" -msgstr "dnsmasq 로그 디렉토리를 작성하는 중에 오류 발생: %s" +msgstr "Dnsmasq 로그 디렉토리를 작성하는 중에 오류 발생: %s" #, python-format msgid "Error while deleting router %s" @@ -408,7 +407,7 @@ msgstr "라우터 %s을(를) 삭제하는 중에 오류 발생" #, python-format msgid "Error while handling pidfile: %s" -msgstr "pidfile을 처리하는 중에 오류 발생: %s" +msgstr "Pidfile을 처리하는 중에 오류 발생: %s" #, python-format msgid "Error while importing BGP speaker driver %s" @@ -419,7 +418,7 @@ msgstr "VIF 포트를 처리하는 중에 오류 발생" #, python-format msgid "Error while writing HA state for %s" -msgstr "%s의 HA 상태를 쓰는 중 오류 발생" +msgstr "%s에대해 HA 상태를 쓰는 중 오류 발생" #, python-format msgid "Error, unable to destroy IPset: %s" @@ -427,7 +426,7 @@ msgstr "오류, IPSet을 영구 삭제할 수 없음: %s" #, python-format msgid "Error, unable to remove iptables rule for IPset: %s" -msgstr "오류, IPset의 iptables 규칙을 제거할 수 없음: %s" +msgstr "오류, IPset에서 iptables 규칙을 제거할 수 없음: %s" #, python-format msgid "" @@ -465,7 +464,7 @@ msgid "Exception occurs when timer stops" msgstr "타이머가 중지할 때 예외가 발생합니다. " msgid "Exception occurs when waiting for timer" -msgstr "타이머를 대기 중일 때 예외가 발생합니다. " +msgstr "타이머가 대기 중일 때 예외가 발생합니다. " msgid "Exiting agent as programmed in check_child_processes_actions" msgstr "check_child_processes_actions에 프로그래밍된 에이전트 종료" @@ -475,8 +474,7 @@ msgid "" "Exiting agent because of a malfunction with the %(service)s process " "identified by uuid %(uuid)s" msgstr "" -"uuid %(uuid)s(으)로 식별된 %(service)s 프로세스의 오동작으로 인해 에이전트 종" -"료" +"UUID %(uuid)s(으)로 식별된 %(service)s 프로세스 오동작으로 인해 에이전트 종료" #, python-format msgid "Expected port %s not found" @@ -492,37 +490,37 @@ msgstr "확장 경로 '%s'이(가) 존재하지 않습니다!" #, python-format msgid "FWaaS RPC failure in %(func_name)s for fw: %(fwid)s" -msgstr "fw %(fwid)s의 %(func_name)s에서 FWaaS RPC 실패" +msgstr "FW %(fwid)s의 %(func_name)s에서 FWaaS RPC 실패" #, python-format msgid "FWaaS RPC info call failed for '%s'." -msgstr "'%s'의 FWaaS RPC 정보 호출에 실패했습니다." +msgstr "'%s' FWaaS RPC 정보 호출에 실패했습니다." #, python-format msgid "Failed creating vxlan interface for %(segmentation_id)s" -msgstr "%(segmentation_id)s의 vxlan 인터페이스를 작성하는 데 실패" +msgstr "%(segmentation_id)s에서 vxlan 인터페이스를 작성하는 데 실패" #, python-format msgid "Failed deleting egress connection state of floatingip %s" -msgstr "floatingip %s의 출구 연결 상태를 삭제하는 데 실패" +msgstr "Floatingip %s의 출구 연결 상태를 삭제하는 데 실패" #, python-format msgid "Failed deleting ingress connection state of floatingip %s" -msgstr "floatingip %s의 진입 연결 상태를 삭제하는 데 실패" +msgstr "Floatingip %s의 진입 연결 상태를 삭제하는 데 실패" #, python-format msgid "Failed execute conntrack command %s" -msgstr "conntrack 명령 %s(으)로 인해 실행 실패" +msgstr "Conntrack 명령 %s(으)로 인해 실행 실패" msgid "Failed executing ip command" msgstr "IP 명령 실행 실패" #, python-format msgid "Failed executing ip command: %s" -msgstr "ip 명령 실행 실패: %s" +msgstr "IP 명령 실행 실패: %s" msgid "Failed fwaas process services sync" -msgstr "fwaas 프로세스 서비스 동기화에 실패" +msgstr "FWaaS 프로세스 서비스 동기화에 실패" msgid "Failed on Agent configuration parse. Agent terminated!" msgstr "에이전트 구성 구문 분석에 실패했습니다. 에이전트가 종료되었습니다!" @@ -566,9 +564,9 @@ msgid "" "agent, since this version of OVS does not support tunnels or patch ports. " "Agent terminated!" msgstr "" -"OVS 패치 포트를 작성하지 못했습니다. 이 버전의 OVS가 터널 또는 패치 포트를 지" -"원하지 않으므로 이 에이전트에서 터널링을 사용할 수 없습니다. 에이전트가 종료" -"되었습니다! " +"OVS 패치 포트를 작성하지 못했습니다. 이 버전 OVS가 터널이나 패치 포트를 지원" +"하지 않으므로 이 에이전트에서 터널링을 사용할 수 없습니다. 에이전트가 종료되" +"었습니다! " #, python-format msgid "Failed to destroy stale namespace %s" @@ -576,19 +574,19 @@ msgstr "시간이 경과된 네임스페이스 %s 영구 삭제 실패" #, python-format msgid "Failed to fetch router information for '%s'" -msgstr "'%s'의 라우터 정보를 가져오는 데 실패" +msgstr "'%s'에대한 라우터 정보를 가져오는 데 실패" #, python-format msgid "Failed to get details for device %s" -msgstr "장치 %s의 세부 사항을 가져오는 데 실패" +msgstr "장치 %s에대한 세부 사항을 가져오는 데 실패" #, python-format msgid "Failed to get devices for %s" -msgstr "%s의 장치를 가져오는 데 실패" +msgstr "%s 장치를 가져오는 데 실패" #, python-format msgid "Failed to get ip addresses for interface: %s." -msgstr "인터페이스의 ip 주소를 가져오는 데 실패: %s." +msgstr "인터페이스에대한 ip 주소를 가져오는 데 실패: %s." msgid "Failed to get network interfaces." msgstr "네트워크 인터페이스를 가져오는 데 실패했습니다." @@ -607,7 +605,7 @@ msgstr "" #, python-format msgid "Failed to notify nova on events: %s" -msgstr "nova에 이벤트에 대해 알리는 데 실패: %s" +msgstr "Nova에 이벤트에 대해 알리는 데 실패: %s" msgid "Failed to parse network_vlan_ranges. Service terminated!" msgstr "" @@ -672,22 +670,22 @@ msgstr "'%s' 인터페이스 연결 해제 실패" #, python-format msgid "Firewall Driver Error for %(func_name)s for fw: %(fwid)s" -msgstr "fw %(fwid)s의 %(func_name)s에서 방화벽 드라이버 오류 발생" +msgstr "FW %(fwid)s의 %(func_name)s에서 방화벽 드라이버 오류 발생" #, python-format msgid "Firewall Driver Error on fw state %(fwmsg)s for fw: %(fwid)s" -msgstr "fw %(fwid)s의 fw 상태 %(fwmsg)s에서 방화벽 드라이버 오류 발생" +msgstr "FW %(fwid)s의 fw 상태 %(fwmsg)s에서 방화벽 드라이버 오류 발생" msgid "Fork failed" msgstr "포크 실패" #, python-format msgid "IP allocation failed on external system for %s" -msgstr "%s의 외부 시스템에서 IP 할당 실패" +msgstr "%s 외부 시스템에서 IP 할당 실패" #, python-format msgid "IP deallocation failed on external system for %s" -msgstr "%s의 외부 시스템에서 IP 할당 해제 실패" +msgstr "%s 외부 시스템에서 IP 할당 해제 실패" #, python-format msgid "IPAM subnet referenced to Neutron subnet %s does not exist" @@ -706,7 +704,7 @@ msgid "" "IPv6 protocol requires a minimum MTU of %(min_mtu)s, while the configured " "value is %(current_mtu)s" msgstr "" -"IPv6 프로토콜에는 최소 %(min_mtu)s의 MTU가 필요한 반면 구성된 값은 " +"IPv6 프로토콜에는 최소 %(min_mtu)s MTU가 필요한 반면 구성된 값은 " "%(current_mtu)s입니다." msgid "" @@ -722,7 +720,7 @@ msgid "" "Interface %(intf)s for physical network %(net)s does not exist. Agent " "terminated!" msgstr "" -"실제 네트워크 %(net)s의 인터페이스 %(intf)s이(가) 없습니다. 에이전트가 종료되" +"실제 네트워크 %(net)s에 인터페이스 %(intf)s이(가) 없습니다. 에이전트가 종료되" "었습니다!" msgid "Interface monitor is not active" @@ -789,8 +787,8 @@ msgid "" "current server timestamp: %(serv_time)s by %(diff)s seconds, which is more " "than the threshold agent downtime: %(threshold)s." msgstr "" -"%(agent_name)s 등록 중에 호스트: %(host)s에서 받은 메시지에 시간소인: " -"%(agent_time)s이(가) 있습니다. 이 시간소인은 현재 서버 시간소인: " +"%(agent_name)s 등록 중에 호스트: %(host)s에서 받은 메시지에 timestamp: " +"%(agent_time)s이(가) 있습니다. 이 timestamp는 현재 서버 timestamp: " "%(serv_time)s과(와) %(diff)s초만큼 차이가 납니다. 이 시간은 임계값 에이전트 " "작동 중단 시간: %(threshold)s보다 큽니다." @@ -806,8 +804,8 @@ msgid "" "Multiple auto-allocated networks detected for tenant %(tenant)s. Attempting " "clean up for network %(network)s and router %(router)s" msgstr "" -"테넌트 %(tenant)s에 대해 자동으로 할당된 여러 네트워크를 발견했습니다. 네트워" -"크 %(network)s 및 라우터 %(router)s을(를) 정리합니다." +"Tenant %(tenant)s에 대해 자동으로 할당된 여러 네트워크를 발견했습니다. 네트워" +"크 %(network)s 나 라우터 %(router)s을(를) 정리합니다." #, python-format msgid "" @@ -845,7 +843,7 @@ msgstr "DVR 포트 %s을(를) 바인드하기 위해 제공된 호스트가 없 #, python-format msgid "No bridge or interface mappings for physical network %s" -msgstr "실제 네트워크 %s의 브릿지 또는 인터페이스 맵핑이 없음" +msgstr "실제 네트워크 %s에서 브릿지나 인터페이스 맵핑이 없음" msgid "No default pools available" msgstr "기본 풀을 사용할 수 없음" @@ -858,7 +856,7 @@ msgid "No local VLAN available for net-id=%s" msgstr "net-id=%s에 대해 사용 가능한 로컬 VLAN이 없음" msgid "No plugin for BGP routing registered" -msgstr "BGP 라우팅의 플러그인이 등록되지 않음" +msgstr "BGP 라우팅에 플러그인이 등록되지 않음" msgid "No plugin for L3 routing registered to handle router scheduling" msgstr "" @@ -868,8 +866,8 @@ msgstr "" msgid "" "No plugin for L3 routing registered. Cannot notify agents with the message %s" msgstr "" -"L3 라우팅의 플러그인이 등록되지 않았습니다. %s 메시지를 에이전트에 알릴 수 없" -"음" +"L3 라우팅에 대한 플러그인이 등록되지 않았습니다. %s 메시지를 에이전트에 알릴 " +"수 없음" msgid "No tunnel_ip specified, cannot delete tunnels" msgstr "tunnel_ip가 지정되지 않음, 터널을 삭제할 수 없음" @@ -901,7 +899,7 @@ msgid "" "Nova notifications are enabled, but novaclient is not installed. Either " "disable nova notifications or install python-novaclient." msgstr "" -"Nova 알림이 사용되지만 novaclient가 설치되지 않았습니다. nova 알림을 사용하" +"Nova 알림이 사용되지만 novaclient가 설치되지 않았습니다. Nova 알림을 사용하" "지 않거나 python-novaclient를 설치하십시오." #, python-format @@ -988,7 +986,7 @@ msgstr "스위치 연결 제한시간 초과" #, python-format msgid "The SNAT namespace %s does not exist for the router." -msgstr "라우터의 SNAT 네임스페이스 %s이(가) 없습니다." +msgstr "라우터에서 SNAT 네임스페이스 %s이(가) 없습니다." #, python-format msgid "The external network bridge '%s' does not exist" @@ -1023,7 +1021,7 @@ msgid "" "The user that is executing neutron does not have permissions to read the " "namespaces. Enable the use_helper_for_ns_read configuration option." msgstr "" -"neutron을 실행하는 사용자는 네임스페이스를 읽을 권한이 없습니다. " +"eutron을 실행하는 사용자는 네임스페이스를 읽을 권한이 없습니다. " "use_helper_for_ns_read 구성 옵션을 사용하십시오." #, python-format @@ -1035,8 +1033,8 @@ msgid "" "Tunneling can't be enabled with invalid local_ip '%s'. IP couldn't be found " "on this host's interfaces." msgstr "" -"올바르지 않은 local_ip '%s'(으)로 터널링을 사용할 수 없습니다. 이 호스트의 인" -"터페이스에서 IP를 찾을 수 없습니다." +"올바르지 않은 local_ip '%s'(으)로 터널링을 사용할 수 없습니다. 이 호스트 인터" +"페이스에서 IP를 찾을 수 없습니다." #, python-format msgid "" @@ -1058,7 +1056,7 @@ msgstr "" #, python-format msgid "Unable to %(action)s dhcp for %(net_id)s." -msgstr "%(net_id)s의 %(action)s dhp을(를) 사용할 수 없습니다." +msgstr "%(net_id)s의 %(action)s dhcp를 사용할 수 없습니다." #, python-format msgid "Unable to add %(interface)s to %(bridge_name)s! Exception: %(e)s" @@ -1066,20 +1064,20 @@ msgstr "%(interface)s을(를) %(bridge_name)s에 추가할 수 없습니다! 예 #, python-format msgid "Unable to add vxlan interface for network %s" -msgstr "네트워크 %s의 vxlan 인터페이스를 추가할 수 없음" +msgstr "네트워크 %s에서 vxlan 인터페이스를 추가할 수 없음" #, python-format msgid "" "Unable to auto allocate topology for tenant %s because of router errors." -msgstr "라우터 오류로 인해 테넌트 %s의 토폴로지를 자동으로 할당할 수 없습니다." +msgstr "라우터 오류로 인해 tenant %s의 토폴로지를 자동으로 할당할 수 없습니다." #, python-format msgid "" "Unable to auto allocate topology for tenant %s due to missing requirements, " "e.g. default or shared subnetpools" msgstr "" -"요구 사항이 누락되어 테넌트 %s의 토폴로지를 자동으로 할당할 수 없습니다(예: " -"기본 또는 공유 subnetpool)" +"요구 사항이 누락되어 tenant %s 토폴로지를 자동으로 할당할 수 없습니다(예: 기" +"본 또는 공유 subnetpool)" #, python-format msgid "Unable to convert value in %s" @@ -1090,16 +1088,16 @@ msgid "" "Unable to create VLAN interface for VLAN ID %s because it is in use by " "another interface." msgstr "" -"다른 인터페이스에서 사용 중이므로 VLAN ID %s의 VLAN인터페이스를 작성할 수 없" -"습니다." +"다른 인터페이스에서 사용 중이므로 VLAN ID %s에대한 VLAN인터페이스를 작성할 " +"수 없습니다." #, python-format msgid "" "Unable to create VXLAN interface for VNI %s because it is in use by another " "interface." msgstr "" -"다른 인터페이스에서 사용 중이므로 VNI %s의 VXLAN인터페이스를 작성할 수 없습니" -"다." +"다른 인터페이스에서 사용 중이므로 VNI %s에대하한 VXLAN인터페이스를 작성할 수 " +"없습니다." #, python-format msgid "Unable to execute %(cmd)s. Exception: %(exception)s" @@ -1122,11 +1120,11 @@ msgstr "%s 시도 후 MAC 주소를 생성할 수 없음" #, python-format msgid "Unable to get port details for %s" -msgstr "%s의 포트 세부 사항을 가져올 수 없음" +msgstr "%s에대한 포트 세부 사항을 가져올 수 없음" #, python-format msgid "Unable to listen on %(host)s:%(port)s" -msgstr "%(host)s:%(port)s에서 청취할 수 없음" +msgstr "%(host)s:%(port)s에서 listen 할 수 없음" msgid "Unable to obtain MAC address for unique ID. Agent terminated!" msgstr "고유 ID에 대한 MAC 주소를 얻을 수 없습니다. 에이전트가 종료됩니다!" @@ -1188,7 +1186,7 @@ msgstr "지원되는 ip 링크 명령을 확인하는 중에 예상치 못한 #, python-format msgid "Unknown network_type %(network_type)s for network %(network_id)s." -msgstr "네트워크 %(network_id)s의 알 수 없는 network_type %(network_type)s." +msgstr "네트워크 %(network_id)s에서 알 수 없는 network_type %(network_type)s." msgid "Unrecoverable error: please check log for details." msgstr "복구할 수 없는 오류: 세부 사항은 로그를 확인하십시오." @@ -1208,8 +1206,8 @@ msgid "" "Will not send event %(method)s for network %(net_id)s: no agent available. " "Payload: %(payload)s" msgstr "" -"네트워크 %(net_id)s의 이벤트 %(method)s을(를) 보내지 않음: 사용할 수 있는 에" -"이전트가 없습니다. 페이로드: %(payload)s" +"네트워크 %(net_id)s 이벤트 %(method)s을(를) 보내지 않음: 사용할 수 있는 에이" +"전트가 없습니다. 페이로드: %(payload)s" #, python-format msgid "_bind_port_if_needed failed, deleting port '%s'" @@ -1259,11 +1257,11 @@ msgstr "포트 %s의 mechanism_manager.update_port_postcommit 실패" #, python-format msgid "ofctl request %(request)s error %(error)s" -msgstr "ofctl 요청 %(request)s 오류 %(error)s" +msgstr "Ofctl 요청 %(request)s 오류 %(error)s" #, python-format msgid "ofctl request %(request)s timed out" -msgstr "ofctl 요청 %(request)s 제한시간 초과" +msgstr "Ofctl 요청 %(request)s 제한시간 초과" #, python-format msgid "tunnel_type %s not supported by agent" diff --git a/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-info.po b/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-info.po index e52a9196082..bd0e986e251 100644 --- a/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-info.po +++ b/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-info.po @@ -3,17 +3,16 @@ # This file is distributed under the same license as the neutron project. # # Translators: -# OpenStack Infra , 2015. #zanata -# SeYeon Lee , 2016. #zanata +# Sungjin Kang , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0rc3.dev4\n" +"Project-Id-Version: neutron 8.0.1.dev29\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-29 10:14+0000\n" +"POT-Creation-Date: 2016-04-10 14:30+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-03-29 01:48+0000\n" +"PO-Revision-Date: 2016-04-08 12:16+0000\n" "Last-Translator: SeYeon Lee \n" "Language: ko-KR\n" "Plural-Forms: nplurals=1; plural=0;\n" @@ -59,7 +58,7 @@ msgstr "%d 프로브가 발견됨" #, python-format msgid "%s Agent RPC Daemon Started!" -msgstr "%s 에이전트 RPC 디먼이 시작되었습니다!" +msgstr "%s 에이전트 RPC 데몬이 시작되었습니다!" #, python-format msgid "%s Agent has just been revived. Doing a full sync." @@ -67,7 +66,7 @@ msgstr "%s 에이전트가 다시 활성화되었습니다. 전체 동기화를 #, python-format msgid "%s Agent out of sync with plugin!" -msgstr "%s 이전트가 플러그인과 동기화되지 않았습니다!" +msgstr "%s 에이전트가 플러그인과 동기화되지 않았습니다!" #, python-format msgid "" @@ -115,7 +114,7 @@ msgid "Agent caught SIGHUP, resetting." msgstr "에이전트에서 SIGHUP을 발견하여, 재설정합니다." msgid "Agent caught SIGTERM, quitting daemon loop." -msgstr "에이전트에서 SIGTERM을 발견하여 디먼 루프를 중단합니다." +msgstr "에이전트에서 SIGTERM을 발견하여 데몬 루프를 중단합니다." msgid "Agent has just been revived. Doing a full sync." msgstr "에이전트가 다시 활성화되었습니다. 전체 동기화를 수행합니다." @@ -247,7 +246,7 @@ msgstr "브릿지 정리: %s" #, python-format msgid "Cleaning stale %s flows" -msgstr "시간이 경과된 %s 플로우 정리" +msgstr "시간 경과된 %s 플로우 정리" #, python-format msgid "Clearing orphaned ARP spoofing entries for devices %s" @@ -289,15 +288,15 @@ msgid "Configured type driver names: %s" msgstr "형식 드라이버 이름을 설정했습니다: %s" msgid "Configuring tunnel endpoints to other OVS agents" -msgstr "다른 OVS 에이전트의 커널 엔드포인트 구성" +msgstr "다른 OVS 에이전트에대한 커널 엔드포인트 구성" #, python-format msgid "Creating instance of CountableResource for resource:%s" -msgstr "자원의 CountableResource 인스턴스 작성:%s" +msgstr "자원에대한 CountableResource 인스턴스 작성:%s" #, python-format msgid "Creating instance of TrackedResource for resource:%s" -msgstr "자원의 TrackedResource 인스턴스 작성:%s" +msgstr "자원에대한 TrackedResource 인스턴스 작성:%s" msgid "DHCP agent started" msgstr "DHCP 에이전트가 시작됨" @@ -342,7 +341,7 @@ msgid "Devices down %s " msgstr "장치 작동 중단 %s" msgid "Disabled allowed-address-pairs extension." -msgstr "허용된 주소 쌍 확장을 사용하지 않습니다." +msgstr "allowed-address-pairs 확장을 사용하지 않습니다." msgid "Disabled security-group extension." msgstr "보안 그룹 확장을 사용하지 않습니다. " @@ -409,7 +408,7 @@ msgid "" "HA network %(network)s was deleted as no HA routers are present in tenant " "%(tenant)s." msgstr "" -"테넌트 %(tenant)s에 HA 라우터가 없으므로 HA 네트워크 %(network)s이(가) 삭제되" +"Tenant %(tenant)s에 HA 라우터가 없으므로 HA 네트워크 %(network)s이(가) 삭제되" "었습니다." #, python-format @@ -442,7 +441,7 @@ msgid "Initializing Linux bridge QoS extension" msgstr "Linux 브릿지 QoS 확장 초기화" msgid "Initializing Ryu driver for BGP Speaker functionality." -msgstr "BGP 스피커 기능의 Ryu 드라이버를 초기화합니다." +msgstr "BGP 스피커 기능에서 Ryu 드라이버를 초기화합니다." #, python-format msgid "Initializing agent extension '%s'" @@ -637,7 +636,7 @@ msgstr "%s 디바이스에 대한 필터 준비" #, python-format msgid "Process runs with uid/gid: %(uid)s/%(gid)s" -msgstr "uid/gid가 %(uid)s/%(gid)s인 프로세스 실행" +msgstr "UID/GID가 %(uid)s/%(gid)s인 프로세스 실행" msgid "Provider rule updated" msgstr "제공자 규칙이 업데이트됨" @@ -684,7 +683,7 @@ msgstr "등록된 형식: %s" #, python-format msgid "Remove device filter for %r" -msgstr "%r의 디바이스 필터 제거" +msgstr "%r 에대한 디바이스 필터 제거" #, python-format msgid "" @@ -737,7 +736,7 @@ msgid "SNAT interface port list does not exist, so create one: %s" msgstr "SNAT 인터페이스 포트 목록이 없으므로, 하나 작성: %s" msgid "SRIOV NIC Agent RPC Daemon Started!" -msgstr "SRIOV NIC 에이전트 RPC 디먼이 시작되었습니다!" +msgstr "SRIOV NIC 에이전트 RPC 데몬이 시작되었습니다!" #, python-format msgid "Scheduling unhosted network %s" @@ -814,19 +813,19 @@ msgstr "상태 동기화 완료" #, python-format msgid "Tenant network_types: %s" -msgstr "network_types를 임대합니다: %s" +msgstr "Tenant network_types: %s" #, python-format msgid "" "The requested interface name %(requested_name)s exceeds the %(limit)d " "character limitation. It was shortened to %(new_name)s to fit." msgstr "" -"요청된 인터페이스 이름 %(requested_name)s이(가) %(limit)d자 한계를 초과합니" -"다. 이 한계에 맞게 %(new_name)s(으)로 단축됩니다." +"요청된 인터페이스 이름 %(requested_name)s이(가) 최대치인 %(limit)d자 이상입니" +"다. 이 제한에 맞게 %(new_name)s(으)로 단축됩니다." #, python-format msgid "Trigger reload_allocations for port %s" -msgstr "포트 %s의 reload_allocations 트리거" +msgstr "포트 %s 에대한 reload_allocations 트리거" #, python-format msgid "" diff --git a/neutron/locale/ko_KR/LC_MESSAGES/neutron.po b/neutron/locale/ko_KR/LC_MESSAGES/neutron.po index db667d94e80..1f440edaae4 100644 --- a/neutron/locale/ko_KR/LC_MESSAGES/neutron.po +++ b/neutron/locale/ko_KR/LC_MESSAGES/neutron.po @@ -8,20 +8,20 @@ # Sungjin Kang , 2013 # Sungjin Kang , 2013 # Sungjin Kang , 2013 -# ChungYoung Cho , 2015. #zanata # Lucas Palm , 2015. #zanata # OpenStack Infra , 2015. #zanata # Lucas Palm , 2016. #zanata # SeYeon Lee , 2016. #zanata +# Sungjin Kang , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0rc3.dev4\n" +"Project-Id-Version: neutron 8.0.1.dev29\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-29 10:14+0000\n" +"POT-Creation-Date: 2016-04-10 14:30+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-03-29 08:19+0000\n" +"PO-Revision-Date: 2016-04-08 12:59+0000\n" "Last-Translator: SeYeon Lee \n" "Language: ko-KR\n" "Plural-Forms: nplurals=1; plural=0;\n" @@ -380,9 +380,9 @@ msgid "" "comments to generated iptables rules that describe each rule's purpose. " "System must support the iptables comments module for addition of comments." msgstr "" -"iptables 규칙에 주석을 추가하십시오. false로 설정하면 각 규칙의 용도를 설명하" -"는 생성된 iptables 규칙에 주석을 추가할 수 없습니다. 시스템에서 주석을 추가하" -"기 위한 iptables 주석 모듈을 지원해야 합니다." +" Iptables 규칙에 주석을 추가하십시오. False로 설정하면 각 규칙의 용도를 설명" +"하는 생성된 iptables 규칙에 주석을 추가할 수 없습니다. 시스템에서 주석을 추가" +"하기 위한 iptables 주석 모듈을 지원해야 합니다." msgid "Address not present on interface" msgstr "인터페이스에 주소가 없음" @@ -559,7 +559,7 @@ msgstr "" "합니다." msgid "Availability zone of this node" -msgstr "이 노드의 가용 구역" +msgstr "노드에대한 가용 구역" #, python-format msgid "AvailabilityZone %(availability_zone)s could not be found." @@ -774,7 +774,7 @@ msgstr "" "할 수 업습니다." msgid "Cannot match priority on flow deletion or modification" -msgstr "플로우 삭제 또는 수정 시 우선순위와 일치할 수 없음" +msgstr "플로우 삭제나 수정시 우선순위와 일치할 수 없음" msgid "Cannot mix IPv4 and IPv6 prefixes in a subnet pool." msgstr "서브넷 풀에서 IPv4 및 IPv6 접두부를 혼합하여 사용할 수 없습니다." @@ -1457,7 +1457,7 @@ msgstr "%s을(를) 읽는 중에 오류 발생" msgid "" "Exceeded %s second limit waiting for address to leave the tentative state." msgstr "" -"주소가 임시 상태를 벗어날 때까지 대기하는 동안 %s초 제한이 초과되어씃ㅂ니다." +"주소가 임시 상태를 벗어날 때까지 대기하는 동안 %s초 제한이 초과되었습니다." msgid "Exceeded maximum amount of fixed ips per port." msgstr "포트당 최대 Fixed IP 수를 초과했습니다." @@ -1610,7 +1610,7 @@ msgstr "보조 그룹을 제거하지 못함" #, python-format msgid "Failed to set gid %s" -msgstr "gid %s을(를) 설정하지 못함" +msgstr "GID %s을(를) 설정하지 못함" #, python-format msgid "Failed to set uid %s" @@ -1713,7 +1713,7 @@ msgstr "" "에이전트 유효 그룹)." msgid "Group (gid or name) running this process after its initialization" -msgstr "초기화 이후 이 프로세스를 실행하는 그룹(gid 또는 이름)" +msgstr "초기화 이후 이 프로세스를 실행하는 그룹(gid 이름)" #, python-format msgid "HEAD file does not match migration timeline head, expected: %s" @@ -2122,7 +2122,7 @@ msgid "Key %(key)s in mapping: '%(mapping)s' not unique" msgstr "'%(mapping)s' 맵핑의 %(key)s 키가 고유하지 않음" msgid "L3 agent failure to setup NAT for floating IPs" -msgstr "L3 에이전트에서 Floating IP의 NAT 설정 실패" +msgstr "L3 에이전트에서 Floating IP에대한 NAT 설정 실패" msgid "L3 agent failure to setup floating IPs" msgstr "L3 에이전트에서 Floating IP 설정 실패" @@ -2174,7 +2174,7 @@ msgid "Location for Metadata Proxy UNIX domain socket." msgstr "메타데이터 프록시 UNIX 도메인 소켓의 위치입니다." msgid "Location of Metadata Proxy UNIX domain socket" -msgstr "메타데이터 프록시 UNIX 도메인 소켓의 위치" +msgstr "메타데이터 프록시 UNIX 도메인 소켓 위치" msgid "Location of pid file of this process." msgstr "이 프로세스의 pid 파일 위치입니다." @@ -2391,7 +2391,7 @@ msgid "Must also specify protocol if port range is given." msgstr "포트 범위가 제공되는 경우 프로토콜도 지정해야 합니다. " msgid "Must specify one or more actions on flow addition or modification" -msgstr "플로우 추가 또는 수정 시 하나 이상의 조치를 지정해야 함" +msgstr "플로우 추가나 수정시 하나 이상의 조치를 지정해야 함" #, python-format msgid "Name %(dns_name)s is duplicated in the external DNS service" @@ -2408,7 +2408,7 @@ msgid "Name '%s' must not start or end with a hyphen." msgstr "이름 '%s'은(는) 하이픈으로 시작하거나 끝날 수 없습니다." msgid "Name of Open vSwitch bridge to use" -msgstr "사용할 열린 vSwitch 브릿지의 이름" +msgstr "사용할 Open vSwitch 브릿지 이름" msgid "" "Name of bridge used for external network traffic. This should be set to an " @@ -2416,7 +2416,7 @@ msgid "" "can be associated with no more than one external network. This option is " "deprecated and will be removed in the M release." msgstr "" -"외부 네트워크 트래픽에 사용되는 브릿지 이름입니다. Linux Bridge의 빈 값으로 " +"외부 네트워크 트래픽에 사용되는 브릿지 이름입니다. Linux Bridge는 빈 값으로 " "설정해야 합니다. 이 매개변수가 설정되면 각 L3 에이전트를 두 개 이상의 외부 네" "트워크에 연관시킬 수 있습니다. 이 옵션은 더 이상 사용되지 않으므로 M 릴리스에" "서 제거됩니다." @@ -2431,7 +2431,7 @@ msgid "Name of the FWaaS Driver" msgstr "FWaaS 드라이버 이름" msgid "Namespace of the router" -msgstr "라우터의 네임스페이스" +msgstr "라우터에대한 네임스페이스" msgid "Native pagination depend on native sorting" msgstr "네이티브 페이지 번호 매기기는 네이티브 정렬에 따라 다름" @@ -2645,7 +2645,7 @@ msgid "" msgstr "보낼 이벤트가 있는 경우 nova에 전송하는 이벤트 간의 시간(초)입니다." msgid "Number of seconds to keep retrying to listen" -msgstr "감청 재시도 계속할 시간" +msgstr "Listen 재시도 계속할 시간" msgid "" "Number of security groups allowed per tenant. A negative value means " @@ -2778,7 +2778,7 @@ msgid "Path to PID file for this process" msgstr "이 프로세스에 대한 PID 파일의 경로" msgid "Path to the router directory" -msgstr "라우터 디렉토리의 경로" +msgstr "라우터 디렉토리 경로" msgid "Peer patch port in integration bridge for tunnel bridge." msgstr "터널 브릿지에 대한 통합 브릿지에 있는 피어 패치 포트입니다." @@ -2846,9 +2846,6 @@ msgid "" "port." msgstr "포트에서 주소 쌍을 허용하려면 포트 보안을 사용 가능하게 해야 합니다." -msgid "Port does not have port security binding." -msgstr "포트에 포트 보안 바인딩이 없습니다. " - msgid "" "Port has security group associated. Cannot disable port security or ip " "address until security group is removed" @@ -3081,7 +3078,7 @@ msgstr "" "고 명령을 직접 실행하기만 하면 됩니다." msgid "Root helper daemon application to use when possible." -msgstr "가능한 경우 사용할 루트 헬퍼 디먼 애플리케이션." +msgstr "가능한 경우 사용할 루트 헬퍼 데몬 애플리케이션." msgid "Root permissions are required to drop privileges." msgstr "권한을 삭제하려면 루트 권한이 필요합니다." @@ -3412,8 +3409,8 @@ msgid "" "transient notification or RPC errors. The interval is number of seconds " "between attempts." msgstr "" -"DHCP 에이전트가 임시 알림 또는 RPC 오류로부터 복구하기 위해 해당 상태를 " -"Neutron과 다시 동기화합니다. 간격은 시도 사이의 초 수입니다." +"DHCP 에이전트가 임시 알림이나 RPC 오류로부터 복구하기 위해 해당 상태를 " +"Neutron과 다시 동기화합니다. 간격은 시도 사이 시간(초) 횟수입니다." msgid "" "The DHCP server can assist with providing metadata support on isolated " @@ -3754,7 +3751,7 @@ msgstr "데이터베이스에 대한 URL" #, python-format msgid "Unable to access %s" -msgstr "%s에 액세스할 수 없음" +msgstr "%s에 접근할 수 없음" #, python-format msgid "" @@ -3810,7 +3807,7 @@ msgstr "" #, python-format msgid "Unable to convert value in %s" -msgstr "%s의 값을 변환할 수 없음" +msgstr "%s 값을 변환할 수 없음" msgid "Unable to create the Agent Gateway Port" msgstr "에이전트 게이트웨이 포트를 작성할 수 없음" @@ -3839,7 +3836,7 @@ msgstr "서브넷 풀을 삭제할 수 없음: %(reason)s." #, python-format msgid "Unable to determine mac address for %s" -msgstr "%s의 맥 주소를 확인할 수 없습니다" +msgstr "%s에대한 맥 주소를 확인할 수 없습니다" #, python-format msgid "Unable to find '%s' in request body" @@ -3994,8 +3991,8 @@ msgid "" "Use ipset to speed-up the iptables based security groups. Enabling ipset " "support requires that ipset is installed on L2 agent node." msgstr "" -"ipset을 사용하여 iptables 기반 보안 그룹의 속도를 높입니다. ipset 지원을 사용" -"하려면 ipset이 L2 에이전트 노드에 설치되어야 합니다." +"IPset을 사용하여 iptables 기반 보안 그룹의 속도를 높입니다. IPset 지원을 사용" +"하려면 IPset이 L2 에이전트 노드에 설치되어야 합니다." msgid "" "Use the root helper when listing the namespaces on a system. This may not be " @@ -4025,7 +4022,7 @@ msgstr "" "우: 에이전트 유효 사용자)." msgid "User (uid or name) running this process after its initialization" -msgstr "초기화 이후 이 프로세스를 실행하는 사용자(uid 또는 이름)" +msgstr "초기화 이후 이 프로세스를 실행하는 사용자(uid나 이름)" msgid "Username for connecting to designate in admin context" msgstr "관리 컨텍스트에서 지정하기 위해 연결할 사용자 이름" diff --git a/neutron/locale/neutron.pot b/neutron/locale/neutron.pot index bd109b49a9c..6f143033f27 100644 --- a/neutron/locale/neutron.pot +++ b/neutron/locale/neutron.pot @@ -6,16 +6,16 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0rc2.dev3\n" +"Project-Id-Version: neutron 8.0.1.dev29\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-18 06:05+0000\n" +"POT-Creation-Date: 2016-04-11 06:27+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.2.0\n" +"Generated-By: Babel 2.3.2\n" #: neutron/manager.py:73 #, python-format @@ -92,33 +92,33 @@ msgstr "" msgid "Enable SSL on the API server" msgstr "" -#: neutron/wsgi.py:159 +#: neutron/wsgi.py:161 #, python-format msgid "Could not bind to %(host)s:%(port)s after trying for %(time)d seconds" msgstr "" -#: neutron/wsgi.py:389 +#: neutron/wsgi.py:391 msgid "Cannot understand JSON" msgstr "" -#: neutron/wsgi.py:555 +#: neutron/wsgi.py:557 msgid "You must implement __call__" msgstr "" -#: neutron/wsgi.py:600 +#: neutron/wsgi.py:602 msgid "Unsupported Content-Type" msgstr "" -#: neutron/wsgi.py:604 +#: neutron/wsgi.py:606 msgid "Malformed request body" msgstr "" -#: neutron/wsgi.py:741 +#: neutron/wsgi.py:743 #, python-format msgid "The requested content type %s is invalid." msgstr "" -#: neutron/wsgi.py:794 +#: neutron/wsgi.py:796 msgid "Could not deserialize data" msgstr "" @@ -650,7 +650,7 @@ msgid "" "%(stderr)s" msgstr "" -#: neutron/agent/linux/openvswitch_firewall/firewall.py:33 +#: neutron/agent/linux/openvswitch_firewall/firewall.py:58 #, python-format msgid "Port %(port_id)s is not managed by this agent. " msgstr "" @@ -1900,50 +1900,54 @@ msgstr "" msgid "Bad prefix type for generate IPv6 address by EUI-64: %s" msgstr "" -#: neutron/common/utils.py:103 +#: neutron/common/utils.py:106 #, python-format msgid "Instance of class %(module)s.%(class)s must contain _cache attribute" msgstr "" -#: neutron/common/utils.py:231 +#: neutron/common/utils.py:236 #: neutron/plugins/ml2/drivers/mech_sriov/agent/common/config.py:37 #, python-format msgid "Invalid mapping: '%s'" msgstr "" -#: neutron/common/utils.py:234 +#: neutron/common/utils.py:239 #: neutron/plugins/ml2/drivers/mech_sriov/agent/common/config.py:40 #, python-format msgid "Missing key in mapping: '%s'" msgstr "" -#: neutron/common/utils.py:237 +#: neutron/common/utils.py:242 #, python-format msgid "Missing value in mapping: '%s'" msgstr "" -#: neutron/common/utils.py:239 +#: neutron/common/utils.py:245 #, python-format msgid "Key %(key)s in mapping: '%(mapping)s' not unique" msgstr "" -#: neutron/common/utils.py:242 +#: neutron/common/utils.py:249 #, python-format msgid "Value %(value)s in mapping: '%(mapping)s' not unique" msgstr "" -#: neutron/common/utils.py:459 +#: neutron/common/utils.py:470 msgid "Illegal IP version number" msgstr "" -#: neutron/common/utils.py:527 neutron/common/utils.py:542 +#: neutron/common/utils.py:538 neutron/common/utils.py:553 msgid "Class not found." msgstr "" -#: neutron/common/utils.py:577 +#: neutron/common/utils.py:588 msgid "'port_max' is smaller than 'port_min'" msgstr "" +#: neutron/common/utils.py:740 +msgid "Method cannot be called within a transaction." +msgstr "" + #: neutron/db/address_scope_db.py:95 msgid "Shared address scope can't be unshared" msgstr "" @@ -2442,11 +2446,11 @@ msgstr "" msgid "The physical network name with which the HA network can be created." msgstr "" -#: neutron/db/l3_hamode_db.py:349 +#: neutron/db/l3_hamode_db.py:360 msgid "add_ha_port cannot be called inside of a transaction." msgstr "" -#: neutron/db/l3_hamode_db.py:483 +#: neutron/db/l3_hamode_db.py:505 msgid "" "Cannot change HA attribute of active routers. Please set router " "admin_state_up to False prior to upgrade." @@ -2464,7 +2468,7 @@ msgstr "" msgid "cannot perform %(event)s due to %(reason)s" msgstr "" -#: neutron/db/securitygroups_db.py:691 +#: neutron/db/securitygroups_db.py:694 msgid "Default security group" msgstr "" @@ -3269,22 +3273,18 @@ msgstr "" msgid "Duplicate segment entry in request." msgstr "" -#: neutron/extensions/portsecurity.py:22 +#: neutron/extensions/portsecurity.py:25 msgid "" "Port has security group associated. Cannot disable port security or ip " "address until security group is removed" msgstr "" -#: neutron/extensions/portsecurity.py:27 +#: neutron/extensions/portsecurity.py:30 msgid "" "Port security must be enabled and port must have an IP address in order " "to use security groups." msgstr "" -#: neutron/extensions/portsecurity.py:32 -msgid "Port does not have port security binding." -msgstr "" - #: neutron/extensions/providernet.py:60 msgid "Plugin does not support updating provider attributes" msgstr "" @@ -3448,13 +3448,13 @@ msgstr "" msgid "'%s' is not an integer or uuid" msgstr "" -#: neutron/extensions/securitygroup.py:284 +#: neutron/extensions/securitygroup.py:289 msgid "" "Number of security groups allowed per tenant. A negative value means " "unlimited." msgstr "" -#: neutron/extensions/securitygroup.py:288 +#: neutron/extensions/securitygroup.py:293 msgid "" "Number of security rules allowed per tenant. A negative value means " "unlimited." @@ -3739,11 +3739,7 @@ msgstr "" msgid "network_type value '%s' not supported" msgstr "" -#: neutron/plugins/ml2/plugin.py:112 -msgid "Method cannot be called within a transaction." -msgstr "" - -#: neutron/plugins/ml2/plugin.py:306 +#: neutron/plugins/ml2/plugin.py:282 msgid "binding:profile value too large" msgstr "" @@ -3995,7 +3991,7 @@ msgstr "" msgid "Device has no virtual functions" msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:425 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:427 #, python-format msgid "Device name %(dev_name)s is missing from physical_device_mappings" msgstr "" @@ -4070,12 +4066,12 @@ msgstr "" msgid "Incorrect pci_vendor_info: \"%s\", should be pair vendor_id:product_id" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:304 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:301 #, python-format msgid "Parsing bridge_mappings failed: %s." msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:2057 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:2055 msgid "" "DVR deployments for VXLAN/GRE/Geneve underlays require L2-pop to be " "enabled, in both the Agent and Server side." @@ -4530,7 +4526,7 @@ msgstr "" msgid "A QoS driver must be specified" msgstr "" -#: neutron/tests/base.py:118 +#: neutron/tests/base.py:114 #, python-format msgid "Unknown attribute '%s'." msgstr "" diff --git a/neutron/locale/pt_BR/LC_MESSAGES/neutron.po b/neutron/locale/pt_BR/LC_MESSAGES/neutron.po index 8d8d8cbe1fa..af6fa92bebd 100644 --- a/neutron/locale/pt_BR/LC_MESSAGES/neutron.po +++ b/neutron/locale/pt_BR/LC_MESSAGES/neutron.po @@ -11,9 +11,9 @@ # Lucas Palm , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0rc2.dev13\n" +"Project-Id-Version: neutron 8.0.1.dev29\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-22 12:05+0000\n" +"POT-Creation-Date: 2016-04-10 14:30+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -2990,9 +2990,6 @@ msgstr "" "A Segurança da Porta deve ser ativada para ter pares de endereços permitidos " "em uma porta." -msgid "Port does not have port security binding." -msgstr "A porta não possui uma ligação de segurança da porta." - msgid "" "Port has security group associated. Cannot disable port security or ip " "address until security group is removed" diff --git a/neutron/locale/ru/LC_MESSAGES/neutron.po b/neutron/locale/ru/LC_MESSAGES/neutron.po index 7a69ec4e2c3..1d181076122 100644 --- a/neutron/locale/ru/LC_MESSAGES/neutron.po +++ b/neutron/locale/ru/LC_MESSAGES/neutron.po @@ -9,9 +9,9 @@ # Lucas Palm , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0rc2.dev10\n" +"Project-Id-Version: neutron 8.0.1.dev29\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-19 23:47+0000\n" +"POT-Creation-Date: 2016-04-10 14:30+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -2971,9 +2971,6 @@ msgstr "" "Необходимо включить защиту порта для получения разрешенных пар адресов на " "порту." -msgid "Port does not have port security binding." -msgstr "Для порта отсутствует привязка защиты порта." - msgid "" "Port has security group associated. Cannot disable port security or ip " "address until security group is removed" diff --git a/neutron/locale/tr_TR/LC_MESSAGES/neutron.po b/neutron/locale/tr_TR/LC_MESSAGES/neutron.po index f932d7095cc..20771e5226e 100644 --- a/neutron/locale/tr_TR/LC_MESSAGES/neutron.po +++ b/neutron/locale/tr_TR/LC_MESSAGES/neutron.po @@ -9,9 +9,9 @@ # OpenStack Infra , 2015. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0b4.dev134\n" +"Project-Id-Version: neutron 8.0.1.dev29\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-12 03:36+0000\n" +"POT-Creation-Date: 2016-04-10 14:30+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -1514,9 +1514,6 @@ msgstr "" "Bağlantı noktasında izin verilen adres çiftlerine sahip olmak için bağlantı " "noktası güvenliği etkin olmalı." -msgid "Port does not have port security binding." -msgstr "Bağlantı noktası bağlantı noktası güvenlik bağına sahip değil." - msgid "" "Port has security group associated. Cannot disable port security or ip " "address until security group is removed" diff --git a/neutron/locale/zh_CN/LC_MESSAGES/neutron.po b/neutron/locale/zh_CN/LC_MESSAGES/neutron.po index 34c1cd644dd..ed1e58affd1 100644 --- a/neutron/locale/zh_CN/LC_MESSAGES/neutron.po +++ b/neutron/locale/zh_CN/LC_MESSAGES/neutron.po @@ -18,9 +18,9 @@ # Lucas Palm , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0rc2.dev3\n" +"Project-Id-Version: neutron 8.0.1.dev29\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-17 15:42+0000\n" +"POT-Creation-Date: 2016-04-10 14:30+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -2714,9 +2714,6 @@ msgid "" "port." msgstr "必须启用端口安全性,以便在端口上具有所允许的地址对。" -msgid "Port does not have port security binding." -msgstr "端口没有端口安全性绑定。" - msgid "" "Port has security group associated. Cannot disable port security or ip " "address until security group is removed" diff --git a/neutron/locale/zh_TW/LC_MESSAGES/neutron.po b/neutron/locale/zh_TW/LC_MESSAGES/neutron.po index 2abe186436a..6510a984533 100644 --- a/neutron/locale/zh_TW/LC_MESSAGES/neutron.po +++ b/neutron/locale/zh_TW/LC_MESSAGES/neutron.po @@ -9,9 +9,9 @@ # Lucas Palm , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0rc2.dev10\n" +"Project-Id-Version: neutron 8.0.1.dev29\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-19 23:47+0000\n" +"POT-Creation-Date: 2016-04-10 14:30+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -2712,9 +2712,6 @@ msgid "" "port." msgstr "必須啟用埠安全,才能在埠上使用位址配對。" -msgid "Port does not have port security binding." -msgstr "埠沒有埠安全連結。" - msgid "" "Port has security group associated. Cannot disable port security or ip " "address until security group is removed" From 2e2d75cbc2be356e962793db42905cecf28730d8 Mon Sep 17 00:00:00 2001 From: Jakub Libosvar Date: Thu, 7 Apr 2016 10:09:13 +0000 Subject: [PATCH 36/51] ovsfw: Load vlan tag from other_config OVS agent stores vlan tag only to other_config before setup_port_filter() is called [1], leaving 'tag' column empty. This patch loads tag from correct place and modifies functional tests accordingly. Closes-Bug: 1566934 [1] https://github.com/openstack/neutron/blob/1efed3a5321a259d27ec4a6e80352d35fc423c11/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py#L821 Change-Id: Iaae46ce7362fedfc53af958600d6d712eb382e9f (cherry picked from commit dabd969090d35ec218d348f170edbef58163a79d) --- .../agent/linux/openvswitch_firewall/firewall.py | 13 +++++++++---- neutron/tests/common/conn_testers.py | 5 +++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/neutron/agent/linux/openvswitch_firewall/firewall.py b/neutron/agent/linux/openvswitch_firewall/firewall.py index ec2402255b3..fbdf86c9d11 100644 --- a/neutron/agent/linux/openvswitch_firewall/firewall.py +++ b/neutron/agent/linux/openvswitch_firewall/firewall.py @@ -16,7 +16,7 @@ import netaddr from oslo_log import log as logging -from neutron._i18n import _, _LE +from neutron._i18n import _, _LE, _LW from neutron.agent import firewall from neutron.agent.linux.openvswitch_firewall import constants as ovsfw_consts from neutron.agent.linux.openvswitch_firewall import rules @@ -245,9 +245,14 @@ class OVSFirewallDriver(firewall.FirewallDriver): raise OVSFWPortNotFound(port_id=port_id) try: - port_vlan_id = int(self.int_br.br.db_get_val( - 'Port', ovs_port.port_name, 'tag')) - except TypeError: + other_config = self.int_br.br.db_get_val( + 'Port', ovs_port.port_name, 'other_config') + port_vlan_id = int(other_config['tag']) + except (KeyError, TypeError): + LOG.warning(_LW("Can't get tag for port %(port_id)s from its " + "other_config: %(other_config)s"), + port_id=port_id, + other_config=other_config) port_vlan_id = ovs_consts.DEAD_VLAN_TAG of_port = OFPort(port, ovs_port, port_vlan_id) self.sg_port_map.create_port(of_port, port) diff --git a/neutron/tests/common/conn_testers.py b/neutron/tests/common/conn_testers.py index 189ee604c5c..948f35ef819 100644 --- a/neutron/tests/common/conn_testers.py +++ b/neutron/tests/common/conn_testers.py @@ -357,6 +357,11 @@ class OVSConnectionTester(ConnectionTester): def set_tag(self, port_name, tag): self.bridge.set_db_attribute('Port', port_name, 'tag', tag) + other_config = self.bridge.db_get_val( + 'Port', port_name, 'other_config') + other_config['tag'] = tag + self.bridge.set_db_attribute( + 'Port', port_name, 'other_config', other_config) def set_vm_tag(self, tag): self.set_tag(self._vm.port.name, tag) From ece192b056c36568238abaf763b0ea9f99877c4c Mon Sep 17 00:00:00 2001 From: Oleg Bondarev Date: Fri, 1 Apr 2016 19:40:20 +0300 Subject: [PATCH 37/51] Use new DB context when checking if agent is online during rescheduling Commit 9ec466cd42de94c2fad091edfd7583a5f47eb87a was not enough since it checked l3 agents in the same transaction that was used to fetch down bindings - so agents always were down even if actually they went back online. This commit adds context creation on each iteration to make sure we use new transaction and fetch up-to-date info for the agent. Closes-Bug: #1522436 Change-Id: I12a4e4f4e0c2042f0c0bf7eead42baca7b87a22b (cherry picked from commit 70068992e37c80e9aa8e70f017aa35132d7e5aee) --- neutron/db/l3_agentschedulers_db.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/neutron/db/l3_agentschedulers_db.py b/neutron/db/l3_agentschedulers_db.py index 7427a71ba7b..10dd82630fd 100644 --- a/neutron/db/l3_agentschedulers_db.py +++ b/neutron/db/l3_agentschedulers_db.py @@ -116,6 +116,10 @@ class L3AgentSchedulerDbMixin(l3agentscheduler.L3AgentSchedulerPluginBase, if binding.l3_agent_id in agents_back_online: continue else: + # we need new context to make sure we use different DB + # transaction - otherwise we may fetch same agent record + # each time due to REPEATABLE_READ isolation level + context = n_ctx.get_admin_context() agent = self._get_agent(context, binding.l3_agent_id) if agent.is_active: agents_back_online.add(binding.l3_agent_id) From fff909e899eb06ca2ba1b9219df8525db0980fdd Mon Sep 17 00:00:00 2001 From: Oleg Bondarev Date: Thu, 7 Apr 2016 19:27:38 +0300 Subject: [PATCH 38/51] Values for [ml2]/physical_network_mtus should not be unique Obviously there could be physical networks with same MTU. The patch sets unique_values to False when parsing physical_network_mtus Unit test added. Closes-Bug: #1567502 Change-Id: I46e5b5d3f7033a974fca40342af6dff7c71a9a4a (cherry picked from commit 5cdd7ae574312a7499a8768c1752d9bc27ff7d20) --- neutron/plugins/ml2/drivers/helpers.py | 6 ++++-- .../tests/unit/plugins/ml2/drivers/test_type_flat.py | 10 ++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/neutron/plugins/ml2/drivers/helpers.py b/neutron/plugins/ml2/drivers/helpers.py index 28e3320d7cb..62fcbb196d3 100644 --- a/neutron/plugins/ml2/drivers/helpers.py +++ b/neutron/plugins/ml2/drivers/helpers.py @@ -19,6 +19,7 @@ from oslo_config import cfg from oslo_db import exception as db_exc from oslo_log import log +from neutron._i18n import _LE from neutron.common import exceptions as exc from neutron.common import utils from neutron.plugins.common import utils as p_utils @@ -36,9 +37,10 @@ class BaseTypeDriver(api.TypeDriver): def __init__(self): try: self.physnet_mtus = utils.parse_mappings( - cfg.CONF.ml2.physical_network_mtus + cfg.CONF.ml2.physical_network_mtus, unique_values=False ) - except Exception: + except Exception as e: + LOG.error(_LE("Failed to parse physical_network_mtus: %s"), e) self.physnet_mtus = [] def get_mtu(self, physical_network=None): diff --git a/neutron/tests/unit/plugins/ml2/drivers/test_type_flat.py b/neutron/tests/unit/plugins/ml2/drivers/test_type_flat.py index bb3d2c7a219..302953a5dc2 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/test_type_flat.py +++ b/neutron/tests/unit/plugins/ml2/drivers/test_type_flat.py @@ -142,6 +142,16 @@ class FlatTypeTest(testlib_api.SqlTestCase): self.driver.physnet_mtus = {} self.assertEqual(0, self.driver.get_mtu('physnet1')) + def test_parse_physical_network_mtus(self): + config.cfg.CONF.set_override( + 'physical_network_mtus', + ['physnet1:1500', 'physnet2:1500', 'physnet3:9000'], + group='ml2') + driver = type_flat.FlatTypeDriver() + self.assertEqual('1500', driver.physnet_mtus['physnet1']) + self.assertEqual('1500', driver.physnet_mtus['physnet2']) + self.assertEqual('9000', driver.physnet_mtus['physnet3']) + class FlatTypeDefaultTest(base.BaseTestCase): From 9c58ae6a70125497a39612f71c53c60a8b35968e Mon Sep 17 00:00:00 2001 From: Eugene Nikanorov Date: Wed, 30 Mar 2016 08:36:58 -0700 Subject: [PATCH 39/51] Wrap all update/delete l3_rpc handlers with retries This is needed for mysql galera multimaster backends. Closes-Bug: #1564144 Change-Id: Ia5a14d5ee91c6672d61904f669e9e845a7f262c9 (cherry picked from commit d8f0ee5ecd67ee6ec956c7fdadce3c2a8e8301bf) --- neutron/api/rpc/handlers/l3_rpc.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/neutron/api/rpc/handlers/l3_rpc.py b/neutron/api/rpc/handlers/l3_rpc.py index cc61dfde2eb..7e5bd94fbdb 100644 --- a/neutron/api/rpc/handlers/l3_rpc.py +++ b/neutron/api/rpc/handlers/l3_rpc.py @@ -219,6 +219,7 @@ class L3RpcCallback(object): plugins = manager.NeutronManager.get_service_plugins() return plugins.keys() + @db_api.retry_db_errors def update_floatingip_statuses(self, context, router_id, fip_statuses): """Update operational status for a floating IP.""" with context.session.begin(subtransactions=True): @@ -273,6 +274,7 @@ class L3RpcCallback(object): 'host': host}) return agent_port + @db_api.retry_db_errors def update_ha_routers_states(self, context, **kwargs): """Update states for HA routers. @@ -296,6 +298,7 @@ class L3RpcCallback(object): {'subnet': {'cidr': prefix}})) return updated_subnets + @db_api.retry_db_errors def delete_agent_gateway_port(self, context, **kwargs): """Delete Floatingip agent gateway port.""" network_id = kwargs.get('network_id') From 07fa3725c5a7fc68a41ed8af53ca2d3aad4c35b9 Mon Sep 17 00:00:00 2001 From: Oleg Bondarev Date: Tue, 5 Apr 2016 16:18:03 +0300 Subject: [PATCH 40/51] ADDRESS_SCOPE_MARK_IDS should not be global for L3 agent Otherwise agent becomes unable to handle more than 1024 routers (including deleted routers) and starts failing. It should be enough to distinguish address scopes inside router namespace, so this patch moves ADDRESS_SCOPE_MARK_IDS set to the RouterInfo class. Closes-Bug: #1566291 Change-Id: I1e43bb3e68db4db93cc1dfc1383af0311bfb0f2d (cherry picked from commit 1cb43734808eded87210d2957d56b70c514d55c3) --- neutron/agent/l3/router_info.py | 11 +++++---- .../tests/unit/agent/l3/test_router_info.py | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/neutron/agent/l3/router_info.py b/neutron/agent/l3/router_info.py index f767c7d139e..e9dbe62f815 100644 --- a/neutron/agent/l3/router_info.py +++ b/neutron/agent/l3/router_info.py @@ -33,7 +33,8 @@ EXTERNAL_DEV_PREFIX = namespaces.EXTERNAL_DEV_PREFIX FLOATINGIP_STATUS_NOCHANGE = object() ADDRESS_SCOPE_MARK_MASK = "0xffff0000" -ADDRESS_SCOPE_MARK_IDS = set(range(1024, 2048)) +ADDRESS_SCOPE_MARK_ID_MIN = 1024 +ADDRESS_SCOPE_MARK_ID_MAX = 2048 DEFAULT_ADDRESS_SCOPE = "noscope" @@ -57,8 +58,10 @@ class RouterInfo(object): router_id, agent_conf, interface_driver, use_ipv6) self.router_namespace = ns self.ns_name = ns.name + self.available_mark_ids = set(range(ADDRESS_SCOPE_MARK_ID_MIN, + ADDRESS_SCOPE_MARK_ID_MAX)) self._address_scope_to_mark_id = { - DEFAULT_ADDRESS_SCOPE: ADDRESS_SCOPE_MARK_IDS.pop()} + DEFAULT_ADDRESS_SCOPE: self.available_mark_ids.pop()} self.iptables_manager = iptables_manager.IptablesManager( use_ipv6=use_ipv6, namespace=self.ns_name) @@ -160,10 +163,8 @@ class RouterInfo(object): address_scope = DEFAULT_ADDRESS_SCOPE if address_scope not in self._address_scope_to_mark_id: - mark_ids = set(self._address_scope_to_mark_id.values()) - available_ids = ADDRESS_SCOPE_MARK_IDS - mark_ids self._address_scope_to_mark_id[address_scope] = ( - available_ids.pop()) + self.available_mark_ids.pop()) mark_id = self._address_scope_to_mark_id[address_scope] # NOTE: Address scopes use only the upper 16 bits of the 32 fwmark diff --git a/neutron/tests/unit/agent/l3/test_router_info.py b/neutron/tests/unit/agent/l3/test_router_info.py index e97159ad077..35c1f247ac5 100644 --- a/neutron/tests/unit/agent/l3/test_router_info.py +++ b/neutron/tests/unit/agent/l3/test_router_info.py @@ -143,6 +143,29 @@ class TestRouterInfo(base.BaseTestCase): ipv4_mangle.add_rule.assert_called_once_with( 'scope', ri.address_scope_mangle_rule('fake_device', 'fake_mark')) + def test_address_scope_mark_ids_handling(self): + mark_ids = set(range(router_info.ADDRESS_SCOPE_MARK_ID_MIN, + router_info.ADDRESS_SCOPE_MARK_ID_MAX)) + ri = router_info.RouterInfo(_uuid(), {}, **self.ri_kwargs) + # first mark id is used for the default address scope + scope_to_mark_id = {router_info.DEFAULT_ADDRESS_SCOPE: mark_ids.pop()} + self.assertEqual(scope_to_mark_id, ri._address_scope_to_mark_id) + self.assertEqual(mark_ids, ri.available_mark_ids) + + # new id should be used for new address scope + ri.get_address_scope_mark_mask('new_scope') + scope_to_mark_id['new_scope'] = mark_ids.pop() + self.assertEqual(scope_to_mark_id, ri._address_scope_to_mark_id) + self.assertEqual(mark_ids, ri.available_mark_ids) + + # new router should have it's own mark ids set + new_mark_ids = set(range(router_info.ADDRESS_SCOPE_MARK_ID_MIN, + router_info.ADDRESS_SCOPE_MARK_ID_MAX)) + new_ri = router_info.RouterInfo(_uuid(), {}, **self.ri_kwargs) + new_mark_ids.pop() + self.assertEqual(new_mark_ids, new_ri.available_mark_ids) + self.assertTrue(ri.available_mark_ids != new_ri.available_mark_ids) + class BasicRouterTestCaseFramework(base.BaseTestCase): def _create_router(self, router=None, **kwargs): From 05a4a34b7e46c2e13a9bd874674804a94f342d0c Mon Sep 17 00:00:00 2001 From: Oleg Bondarev Date: Thu, 7 Apr 2016 16:45:52 +0300 Subject: [PATCH 41/51] Notify resource_versions from agents only when needed resource_versions were included into agent state reports recently to support rolling upgrades (commit 97a272a892fcf488949eeec4959156618caccae8) The downside is that it brought additional processing when handling state reports on server side: update of local resources versions cache and more seriously rpc casts to all other servers to do the same. All this led to a visible performance degradation at scale with hundreds of agents constantly sending reports. Under load (rally test) agents may start "blinking" which makes cluster very unstable. In fact there is no need to send and update resource_versions in each state report. I see two cases when it should be done: 1) agent was restarted (after it was upgraded); 2) agent revived - which means that server was not receiving or being able to process state reports for some time (agent_down_time). During that time agent might be upgraded and restarted. So this patch makes agents include resource_versions info only on startup. After agent revival server itself will update version_manager with resource_versions taken from agent DB record - this is to avoid version_manager being outdated. Closes-Bug: #1567497 Change-Id: I47a9869801f4e8f8af2a656749166b6fb49bcd3b (cherry picked from commit e532ee3fccd0820f9ab0efc417ee787fb8c870e9) --- neutron/db/agents_db.py | 18 +++++-- .../ml2/drivers/agent/_common_agent.py | 2 + .../mech_sriov/agent/sriov_nic_agent.py | 3 ++ .../openvswitch/agent/ovs_neutron_agent.py | 2 + neutron/tests/unit/db/test_agents_db.py | 53 +++++++++++++++++-- 5 files changed, 70 insertions(+), 8 deletions(-) diff --git a/neutron/db/agents_db.py b/neutron/db/agents_db.py index 6f6f405ab0d..89a503d259b 100644 --- a/neutron/db/agents_db.py +++ b/neutron/db/agents_db.py @@ -336,8 +336,10 @@ class AgentDbMixin(ext_agent.AgentPluginBase, AgentAvailabilityZoneMixin): res['availability_zone'] = agent_state['availability_zone'] configurations_dict = agent_state.get('configurations', {}) res['configurations'] = jsonutils.dumps(configurations_dict) - resource_versions_dict = agent_state.get('resource_versions', {}) - res['resource_versions'] = jsonutils.dumps(resource_versions_dict) + resource_versions_dict = agent_state.get('resource_versions') + if resource_versions_dict: + res['resource_versions'] = jsonutils.dumps( + resource_versions_dict) res['load'] = self._get_agent_load(agent_state) current_time = timeutils.utcnow() try: @@ -345,6 +347,13 @@ class AgentDbMixin(ext_agent.AgentPluginBase, AgentAvailabilityZoneMixin): context, agent_state['agent_type'], agent_state['host']) if not agent_db.is_active: status = constants.AGENT_REVIVED + if 'resource_versions' not in agent_state: + # updating agent_state with resource_versions taken + # from db so that + # _update_local_agent_resource_versions() will call + # version_manager and bring it up to date + agent_state['resource_versions'] = self._get_dict( + agent_db, 'resource_versions') res['heartbeat_timestamp'] = current_time if agent_state.get('start_flag'): res['started_at'] = current_time @@ -458,7 +467,10 @@ class AgentExtRpcCallback(object): return agent_status def _update_local_agent_resource_versions(self, context, agent_state): - resource_versions_dict = agent_state.get('resource_versions', {}) + resource_versions_dict = agent_state.get('resource_versions') + if not resource_versions_dict: + return + version_manager.update_versions( version_manager.AgentConsumer(agent_type=agent_state['agent_type'], host=agent_state['host']), diff --git a/neutron/plugins/ml2/drivers/agent/_common_agent.py b/neutron/plugins/ml2/drivers/agent/_common_agent.py index 39626c0a8b6..fe884554d0e 100644 --- a/neutron/plugins/ml2/drivers/agent/_common_agent.py +++ b/neutron/plugins/ml2/drivers/agent/_common_agent.py @@ -123,6 +123,8 @@ class CommonAgentLoop(service.Service): 'Doing a full sync.'), self.agent_type) self.fullsync = True + # we only want to update resource versions on startup + self.agent_state.pop('resource_versions', None) self.agent_state.pop('start_flag', None) except Exception: LOG.exception(_LE("Failed reporting state!")) diff --git a/neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py b/neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py index c6134baed7d..53481cd816a 100644 --- a/neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py +++ b/neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py @@ -174,6 +174,9 @@ class SriovNicSwitchAgent(object): self.agent_state.get('configurations')['devices'] = devices self.state_rpc.report_state(self.context, self.agent_state) + + # we only want to update resource versions on startup + self.agent_state.pop('resource_versions', None) self.agent_state.pop('start_flag', None) except Exception: LOG.exception(_LE("Failed reporting state!")) diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py index ed47a6aa0f1..eb27006fd5d 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py @@ -316,6 +316,8 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin, 'Doing a full sync.')) self.fullsync = True + # we only want to update resource versions on startup + self.agent_state.pop('resource_versions', None) if self.agent_state.pop('start_flag', None): # On initial start, we notify systemd after initialization # is complete. diff --git a/neutron/tests/unit/db/test_agents_db.py b/neutron/tests/unit/db/test_agents_db.py index 740d15ad437..3e30c0eae0f 100644 --- a/neutron/tests/unit/db/test_agents_db.py +++ b/neutron/tests/unit/db/test_agents_db.py @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import copy import datetime import mock @@ -27,7 +28,6 @@ from neutron.common import exceptions as n_exc from neutron import context from neutron.db import agents_db from neutron.db import db_base_plugin_v2 as base_plugin -from neutron.tests import base from neutron.tests.unit import testlib_api # the below code is required for the following reason @@ -271,14 +271,13 @@ class TestAgentsDbGetAgents(TestAgentsDbBase): self.assertEqual(alive, agent['alive']) -class TestAgentExtRpcCallback(base.BaseTestCase): +class TestAgentExtRpcCallback(TestAgentsDbBase): def setUp(self): super(TestAgentExtRpcCallback, self).setUp() - self.plugin = mock.Mock() - self.context = mock.Mock() self.callback = agents_db.AgentExtRpcCallback(self.plugin) self.callback.server_versions_rpc = mock.Mock() + self.versions_rpc = self.callback.server_versions_rpc self.callback.START_TIME = datetime.datetime(datetime.MINYEAR, 1, 1) self.update_versions = mock.patch( 'neutron.api.rpc.callbacks.version_manager.' @@ -296,6 +295,50 @@ class TestAgentExtRpcCallback(base.BaseTestCase): callback.report_state(self.context, agent_state=self.agent_state, time=TEST_TIME) report_agent_resource_versions = ( - callback.server_versions_rpc.report_agent_resource_versions) + self.versions_rpc.report_agent_resource_versions) report_agent_resource_versions.assert_called_once_with( mock.ANY, mock.ANY, mock.ANY, TEST_RESOURCE_VERSIONS) + + def test_no_version_updates_on_further_state_reports(self): + self.test_create_or_update_agent_updates_version_manager() + # agents include resource_versions only in the first report after + # start so versions should not be updated on the second report + second_agent_state = copy.deepcopy(self.agent_state) + second_agent_state['agent_state'].pop('resource_versions') + self.update_versions.reset_mock() + report_agent_resource_versions = ( + self.versions_rpc.report_agent_resource_versions) + report_agent_resource_versions.reset_mock() + + self.callback.report_state(self.context, + agent_state=second_agent_state, + time=TEST_TIME) + self.assertFalse(self.update_versions.called) + self.assertFalse(report_agent_resource_versions.called) + + def test_version_updates_on_agent_revival(self): + self.test_create_or_update_agent_updates_version_manager() + second_agent_state = copy.deepcopy(self.agent_state) + second_agent_state['agent_state'].pop('resource_versions') + self._take_down_agent() + self.update_versions.reset_mock() + report_agent_resource_versions = ( + self.versions_rpc.report_agent_resource_versions) + report_agent_resource_versions.reset_mock() + + # agent didn't include resource_versions in report but server will + # take them from db for the revived agent + self.callback.report_state(self.context, + agent_state=second_agent_state, + time=TEST_TIME) + self.update_versions.assert_called_once_with( + mock.ANY, TEST_RESOURCE_VERSIONS) + report_agent_resource_versions.assert_called_once_with( + mock.ANY, mock.ANY, mock.ANY, TEST_RESOURCE_VERSIONS) + + def _take_down_agent(self): + with self.context.session.begin(subtransactions=True): + query = self.context.session.query(agents_db.Agent) + agt = query.first() + agt.heartbeat_timestamp = ( + agt.heartbeat_timestamp - datetime.timedelta(hours=1)) From 07401352a964b92ef4bc09a09800554e4a84cc87 Mon Sep 17 00:00:00 2001 From: Hynek Mlnarik Date: Thu, 25 Feb 2016 11:34:15 +0100 Subject: [PATCH 42/51] Cleanup stale OVS flows for physical bridges Perform deletion of the stale flows in physical bridges consistently with br-int and br-tun, respecting drop_flows_on_start configuration option. Added tests for auxiliary bridge and functional tests for the physical bridge using VLAN/flat external network. Fixes part of the bug 1514056; together with [1] and [2], the bug should be considered fixed. The commit also fixes inconsistency between netmask of allocated IP addresses assigned in _create_test_port_dict and ip_len in _plug_ports of base.py. [1] https://review.openstack.org/#/c/297211/ [2] https://review.openstack.org/#/c/297818/ Co-Authored-By: Jian Wen Partial-Bug: 1514056 Change-Id: I9801b76829021c9a0e6358982e1136637634a521 (cherry picked from commit cacde308eef6f1d7005e555b4521332da95d3cf4) --- .../agent/openflow/native/br_phys.py | 1 - .../agent/openflow/ovs_ofctl/br_phys.py | 1 - .../openvswitch/agent/ovs_neutron_agent.py | 3 ++ neutron/tests/functional/agent/l2/base.py | 40 +++++++++++----- .../functional/agent/test_l2_ovs_agent.py | 46 +++++++++++++++++++ .../agent/openflow/native/test_br_phys.py | 1 - .../agent/openflow/ovs_ofctl/test_br_phys.py | 1 - .../openvswitch/agent/test_ovs_tunnel.py | 39 +++++++++++++--- 8 files changed, 111 insertions(+), 21 deletions(-) diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/br_phys.py b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/br_phys.py index a3aad0fc7ed..9b5d5754760 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/br_phys.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/br_phys.py @@ -30,7 +30,6 @@ class OVSPhysicalBridge(ovs_bridge.OVSAgentBridge, dvr_process_next_table_id = constants.LOCAL_VLAN_TRANSLATION def setup_default_table(self): - self.delete_flows() self.install_normal() @staticmethod diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_phys.py b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_phys.py index e76b7ddaf7f..ff9d87e5405 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_phys.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/br_phys.py @@ -30,7 +30,6 @@ class OVSPhysicalBridge(ovs_bridge.OVSAgentBridge, dvr_process_next_table_id = constants.LOCAL_VLAN_TRANSLATION def setup_default_table(self): - self.delete_flows() self.install_normal() def provision_local_vlan(self, port, lvid, segmentation_id, distributed): diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py index ed47a6aa0f1..2e123a935bf 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py @@ -1090,6 +1090,8 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin, # handle things like changing the datapath_type br.create() br.setup_controllers(self.conf) + if cfg.CONF.AGENT.drop_flows_on_start: + br.delete_flows() br.setup_default_table() self.phys_brs[physical_network] = br @@ -1741,6 +1743,7 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin, def cleanup_stale_flows(self): bridges = [self.int_br] + bridges.extend(self.phys_brs.values()) if self.enable_tunneling: bridges.append(self.tun_br) for bridge in bridges: diff --git a/neutron/tests/functional/agent/l2/base.py b/neutron/tests/functional/agent/l2/base.py index f7d8d227ab8..2ba41006090 100644 --- a/neutron/tests/functional/agent/l2/base.py +++ b/neutron/tests/functional/agent/l2/base.py @@ -184,18 +184,20 @@ class OVSAgentTestFramework(base.BaseOVSLinuxTestCase): return {'id': uuidutils.generate_uuid(), 'tenant_id': uuidutils.generate_uuid()} - def _plug_ports(self, network, ports, agent, ip_len=24, - bridge=None): + def _plug_ports(self, network, ports, agent, + bridge=None, namespace=None): + if namespace is None: + namespace = self.namespace for port in ports: bridge = bridge or agent.int_br self.driver.plug( network.get('id'), port.get('id'), port.get('vif_name'), port.get('mac_address'), - bridge.br_name, namespace=self.namespace) - ip_cidrs = ["%s/%s" % (port.get('fixed_ips')[0][ - 'ip_address'], ip_len)] + bridge.br_name, namespace=namespace) + ip_cidrs = ["%s/8" % (port.get('fixed_ips')[0][ + 'ip_address'])] self.driver.init_l3(port.get('vif_name'), ip_cidrs, - namespace=self.namespace) + namespace=namespace) def _unplug_ports(self, ports, agent): for port in ports: @@ -206,9 +208,9 @@ class OVSAgentTestFramework(base.BaseOVSLinuxTestCase): dev = {'device': port['id'], 'port_id': port['id'], 'network_id': network['id'], - 'network_type': 'vlan', - 'physical_network': 'physnet', - 'segmentation_id': 1, + 'network_type': network.get('network_type', 'vlan'), + 'physical_network': network.get('physical_network', 'physnet'), + 'segmentation_id': network.get('segmentation_id', 1), 'fixed_ips': port['fixed_ips'], 'device_owner': 'compute', 'port_security_enabled': True, @@ -367,12 +369,13 @@ class OVSAgentTestFramework(base.BaseOVSLinuxTestCase): ancillary_bridge=None, trigger_resync=False, failed_dev_up=False, - failed_dev_down=False): + failed_dev_down=False, + network=None): self.ports = port_dicts self.agent = self.create_agent(create_tunnels=create_tunnels, ancillary_bridge=ancillary_bridge) self.polling_manager = self.start_agent(self.agent, ports=self.ports) - self.network = self._create_test_network_dict() + self.network = network or self._create_test_network_dict() if trigger_resync: self._prepare_resync_trigger(self.agent) elif failed_dev_up: @@ -382,3 +385,18 @@ class OVSAgentTestFramework(base.BaseOVSLinuxTestCase): self._plug_ports(self.network, self.ports, self.agent, bridge=ancillary_bridge) + + def plug_ports_to_phys_br(self, network, ports, namespace=None): + physical_network = network.get('physical_network', 'physnet') + phys_segmentation_id = network.get('segmentation_id', None) + network_type = network.get('network_type', 'flat') + + phys_br = self.agent.phys_brs[physical_network] + + self._plug_ports(network, ports, self.agent, bridge=phys_br, + namespace=namespace) + + if phys_segmentation_id and network_type == 'vlan': + for port in ports: + phys_br.set_db_attribute( + "Port", port['vif_name'], "tag", phys_segmentation_id) diff --git a/neutron/tests/functional/agent/test_l2_ovs_agent.py b/neutron/tests/functional/agent/test_l2_ovs_agent.py index 07d1976b87c..d81395fe323 100644 --- a/neutron/tests/functional/agent/test_l2_ovs_agent.py +++ b/neutron/tests/functional/agent/test_l2_ovs_agent.py @@ -180,6 +180,52 @@ class TestOVSAgent(base.OVSAgentTestFramework): self.agent.setup_integration_br() time.sleep(0.25) + def test_assert_pings_during_br_phys_setup_not_lost_in_vlan_to_flat(self): + provider_net = self._create_test_network_dict() + provider_net['network_type'] = 'flat' + + self._test_assert_pings_during_br_phys_setup_not_lost(provider_net) + + def test_assert_pings_during_br_phys_setup_not_lost_in_vlan_to_vlan(self): + provider_net = self._create_test_network_dict() + provider_net['network_type'] = 'vlan' + provider_net['segmentation_id'] = 876 + + self._test_assert_pings_during_br_phys_setup_not_lost(provider_net) + + def _test_assert_pings_during_br_phys_setup_not_lost(self, provider_net): + # Separate namespace is needed when pinging from one port to another, + # otherwise Linux ping uses loopback instead for sending and receiving + # ping, hence ignoring flow setup. + ns_phys = self.useFixture(net_helpers.NamespaceFixture()).name + + ports = self.create_test_ports(amount=2) + port_int = ports[0] + port_phys = ports[1] + ip_int = port_int['fixed_ips'][0]['ip_address'] + ip_phys = port_phys['fixed_ips'][0]['ip_address'] + + self.setup_agent_and_ports(port_dicts=[port_int], create_tunnels=False, + network=provider_net) + + self.plug_ports_to_phys_br(provider_net, [port_phys], + namespace=ns_phys) + + # The OVS agent doesn't monitor the physical bridges, no notification + # is sent when a port is up on a physical bridge, hence waiting only + # for the ports connected to br-int + self.wait_until_ports_state([port_int], up=True) + + with net_helpers.async_ping(ns_phys, [ip_int]) as done: + while not done(): + self.agent.setup_physical_bridges(self.agent.bridge_mappings) + time.sleep(0.25) + + with net_helpers.async_ping(self.namespace, [ip_phys]) as done: + while not done(): + self.agent.setup_physical_bridges(self.agent.bridge_mappings) + time.sleep(0.25) + def test_assert_patch_port_ofports_dont_change(self): # When the integration bridge is setup, it should reuse the existing # patch ports between br-int and br-tun. diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/native/test_br_phys.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/native/test_br_phys.py index 2b33862ef80..53ffb467719 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/native/test_br_phys.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/native/test_br_phys.py @@ -39,7 +39,6 @@ class OVSPhysicalBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase, self.br.setup_default_table() (dp, ofp, ofpp) = self._get_dp() expected = [ - call.delete_flows(), call._send_msg(ofpp.OFPFlowMod(dp, cookie=self.stamp, instructions=[ diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/test_br_phys.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/test_br_phys.py index 47ca3177dc9..ab372977bff 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/test_br_phys.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/test_br_phys.py @@ -37,7 +37,6 @@ class OVSPhysicalBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase, def test_setup_default_table(self): self.br.setup_default_table() expected = [ - call.delete_flows(), call.add_flow(priority=0, table=0, actions='normal'), ] self.assertEqual(expected, self.mock.mock_calls) diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py index 8d3f9b9e761..4111551b3aa 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py @@ -82,6 +82,7 @@ class TunnelTest(object): self.INT_BRIDGE = 'integration_bridge' self.TUN_BRIDGE = 'tunnel_bridge' self.MAP_TUN_BRIDGE = 'tun_br_map' + self.AUX_BRIDGE = 'ancillary_bridge' self.NET_MAPPING = ['net1:%s' % self.MAP_TUN_BRIDGE] self.INT_OFPORT = 11111 self.TUN_OFPORT = 22222 @@ -109,6 +110,8 @@ class TunnelTest(object): self.br_tun_cls('br-tun')), self.MAP_TUN_BRIDGE: mock.create_autospec( self.br_phys_cls('br-phys')), + self.AUX_BRIDGE: mock.create_autospec( + ovs_lib.OVSBridge('br-aux')), } self.ovs_int_ofports = { 'patch-tun': self.TUN_OFPORT, @@ -127,6 +130,10 @@ class TunnelTest(object): self.mock_tun_bridge_cls = mock.patch(self._BR_TUN_CLASS, autospec=True).start() self.mock_tun_bridge_cls.side_effect = lookup_br + self.mock_aux_bridge_cls = mock.patch( + 'neutron.agent.common.ovs_lib.OVSBridge', + autospec=True).start() + self.mock_aux_bridge_cls.side_effect = lookup_br self.mock_int_bridge = self.ovs_bridges[self.INT_BRIDGE] self.mock_int_bridge.add_port.return_value = self.MAP_TUN_INT_OFPORT @@ -157,7 +164,13 @@ class TunnelTest(object): 'get_bridges').start() self.get_bridges.return_value = [self.INT_BRIDGE, self.TUN_BRIDGE, - self.MAP_TUN_BRIDGE] + self.MAP_TUN_BRIDGE, + self.AUX_BRIDGE] + self.get_bridge_external_bridge_id = mock.patch.object( + ovs_lib.BaseOVS, + 'get_bridge_external_bridge_id').start() + self.get_bridge_external_bridge_id.side_effect = ( + lambda bridge: bridge if bridge in self.ovs_bridges else None) self.execute = mock.patch('neutron.agent.common.utils.execute').start() @@ -211,6 +224,10 @@ class TunnelTest(object): 'options', {'peer': 'int-%s' % self.MAP_TUN_BRIDGE}), ] + self.mock_aux_bridge = self.ovs_bridges[self.AUX_BRIDGE] + self.mock_aux_bridge_expected = [ + ] + self.mock_tun_bridge_expected = [ mock.call.create(secure_mode=True), mock.call.setup_controllers(mock.ANY), @@ -286,6 +303,8 @@ class TunnelTest(object): self.mock_map_tun_bridge_expected) self._verify_mock_call(self.mock_tun_bridge, self.mock_tun_bridge_expected) + self._verify_mock_call(self.mock_aux_bridge, + self.mock_aux_bridge_expected) self._verify_mock_call(self.ipdevice, self.ipdevice_expected) self._verify_mock_call(self.ipwrapper, self.ipwrapper_expected) self._verify_mock_call(self.get_bridges, self.get_bridges_expected) @@ -530,8 +549,16 @@ class TunnelTest(object): self.mock_int_bridge_expected += [ mock.call.check_canary_table(), + mock.call.cleanup_flows(), mock.call.check_canary_table() ] + self.mock_tun_bridge_expected += [ + mock.call.cleanup_flows() + ] + self.mock_map_tun_bridge_expected += [ + mock.call.cleanup_flows() + ] + # No cleanup is expected on ancillary bridge self.ovs_bridges[self.INT_BRIDGE].check_canary_table.return_value = \ constants.OVS_NORMAL @@ -547,10 +574,7 @@ class TunnelTest(object): mock.patch.object(time, 'sleep'),\ mock.patch.object( self.mod_agent.OVSNeutronAgent, - 'update_stale_ofport_rules') as update_stale,\ - mock.patch.object( - self.mod_agent.OVSNeutronAgent, - 'cleanup_stale_flows') as cleanup: + 'update_stale_ofport_rules') as update_stale: log_exception.side_effect = Exception( 'Fake exception to get out of the loop') update_stale.return_value = [] @@ -593,7 +617,6 @@ class TunnelTest(object): 'added': set(['tap0'])}, False), ]) - cleanup.assert_called_once_with() self.assertTrue(update_stale.called) self._verify_mock_calls() @@ -649,6 +672,10 @@ class TunnelTestUseVethInterco(TunnelTest): mock.call.drop_port(in_port=self.MAP_TUN_PHY_OFPORT), ] + self.mock_aux_bridge = self.ovs_bridges[self.AUX_BRIDGE] + self.mock_aux_bridge_expected = [ + ] + self.mock_tun_bridge_expected = [ mock.call.create(secure_mode=True), mock.call.setup_controllers(mock.ANY), From 36305c0c4f4ebf498020f5956e103832da75f8a9 Mon Sep 17 00:00:00 2001 From: Kevin Benton Date: Thu, 18 Feb 2016 03:48:29 -0800 Subject: [PATCH 43/51] Add ALLOCATING state to routers This patch adds a new ALLOCATING status to routers to indicate that the routers are still being built on the Neutron server. Any routers in this state are excluded in router retrievals by the L3 agent since they are not yet ready to be wired up. This is necessary when a router is made up of several distinct Neutron resources that cannot all be put into a single transaction. This patch applies this new state to HA routers while their internal HA ports and networks are being created/deleted so the L3 HA agent will never retrieve a partially formed HA router. It's important to note that the ALLOCATING status carries over until after the scheduling is done, which ensures that routers that weren't fully scheduled will not be sent to the agents. An HA router is placed in this state only when it is being created or converted to/from the HA state since this is disruptive to the dataplane. This patch also reverts the changes introduced in Iadb5a69d4cbc2515fb112867c525676cadea002b since they will be handled by the ALLOCATING logic instead. Co-Authored-By: Ann Kamyshnikova Co-Authored-By: John Schwarz APIImpact Closes-Bug: #1550886 Related-bug: #1499647 Change-Id: I22ff5a5a74527366da8f82982232d4e70e455570 (cherry picked from commit 9c3c19f07ce52e139d431aec54341c38a183f0b7) --- neutron/common/constants.py | 5 + neutron/db/l3_agentschedulers_db.py | 12 +- neutron/db/l3_db.py | 26 +++- neutron/db/l3_hamode_db.py | 58 +++++--- neutron/scheduler/l3_agent_scheduler.py | 6 +- neutron/tests/fullstack/test_l3_agent.py | 2 - .../scheduler/test_l3_agent_scheduler.py | 1 + neutron/tests/unit/db/test_l3_hamode_db.py | 134 ++++++++++-------- .../unit/scheduler/test_l3_agent_scheduler.py | 13 +- 9 files changed, 160 insertions(+), 97 deletions(-) diff --git a/neutron/common/constants.py b/neutron/common/constants.py index 21d9b0869a7..0444f782965 100644 --- a/neutron/common/constants.py +++ b/neutron/common/constants.py @@ -23,6 +23,11 @@ from neutron.common import _deprecate ROUTER_PORT_OWNERS = lib_constants.ROUTER_INTERFACE_OWNERS_SNAT + \ (lib_constants.DEVICE_OWNER_ROUTER_GW,) +ROUTER_STATUS_ACTIVE = 'ACTIVE' +# NOTE(kevinbenton): a BUILD status for routers could be added in the future +# for agents to indicate when they are wiring up the ports. The following is +# to indicate when the server is busy building sub-components of a router +ROUTER_STATUS_ALLOCATING = 'ALLOCATING' L3_AGENT_MODE_DVR = 'dvr' L3_AGENT_MODE_DVR_SNAT = 'dvr_snat' L3_AGENT_MODE_LEGACY = 'legacy' diff --git a/neutron/db/l3_agentschedulers_db.py b/neutron/db/l3_agentschedulers_db.py index 10dd82630fd..0298251a081 100644 --- a/neutron/db/l3_agentschedulers_db.py +++ b/neutron/db/l3_agentschedulers_db.py @@ -347,11 +347,13 @@ class L3AgentSchedulerDbMixin(l3agentscheduler.L3AgentSchedulerPluginBase, router_ids): if n_utils.is_extension_supported(self, constants.L3_HA_MODE_EXT_ALIAS): - return self.get_ha_sync_data_for_host(context, host, agent, - router_ids=router_ids, - active=True) - - return self.get_sync_data(context, router_ids=router_ids, active=True) + routers = self.get_ha_sync_data_for_host(context, host, agent, + router_ids=router_ids, + active=True) + else: + routers = self.get_sync_data(context, router_ids=router_ids, + active=True) + return self.filter_allocating_and_missing_routers(context, routers) def list_router_ids_on_host(self, context, host, router_ids=None): agent = self._get_agent_by_type_and_host( diff --git a/neutron/db/l3_db.py b/neutron/db/l3_db.py index 77b02ac13ff..c8942ba9f12 100644 --- a/neutron/db/l3_db.py +++ b/neutron/db/l3_db.py @@ -174,17 +174,41 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, self._apply_dict_extend_functions(l3.ROUTERS, res, router) return self._fields(res, fields) + def filter_allocating_and_missing_routers(self, context, routers): + """Filter out routers that shouldn't go to the agent. + + Any routers in the ALLOCATING state will be excluded by + this query because this indicates that the server is still + building necessary dependent sub-resources for the router and it + is not ready for consumption by the agent. It will also filter + out any routers that no longer exist to prevent conditions where + only part of a router's information was populated in sync_routers + due to it being deleted during the sync. + """ + router_ids = set(r['id'] for r in routers) + query = (context.session.query(Router.id). + filter( + Router.id.in_(router_ids), + Router.status != l3_constants.ROUTER_STATUS_ALLOCATING)) + valid_routers = set(r.id for r in query) + if router_ids - valid_routers: + LOG.debug("Removing routers that were either concurrently " + "deleted or are in the ALLOCATING state: %s", + (router_ids - valid_routers)) + return [r for r in routers if r['id'] in valid_routers] + def _create_router_db(self, context, router, tenant_id): """Create the DB object.""" with context.session.begin(subtransactions=True): # pre-generate id so it will be available when # configuring external gw port + status = router.get('status', l3_constants.ROUTER_STATUS_ACTIVE) router_db = Router(id=(router.get('id') or uuidutils.generate_uuid()), tenant_id=tenant_id, name=router['name'], admin_state_up=router['admin_state_up'], - status="ACTIVE", + status=status, description=router.get('description')) context.session.add(router_db) return router_db diff --git a/neutron/db/l3_hamode_db.py b/neutron/db/l3_hamode_db.py index 695f4ae1084..6cb8060e9de 100644 --- a/neutron/db/l3_hamode_db.py +++ b/neutron/db/l3_hamode_db.py @@ -414,9 +414,11 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin, self._core_plugin.delete_port(admin_ctx, port_id, l3_port_check=False) - def _notify_ha_interfaces_updated(self, context, router_id): + def _notify_ha_interfaces_updated(self, context, router_id, + schedule_routers=True): self.l3_rpc_notifier.routers_updated( - context, [router_id], shuffle_agents=True) + context, [router_id], shuffle_agents=True, + schedule_routers=schedule_routers) @classmethod def _is_ha(cls, router): @@ -441,6 +443,11 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin, def create_router(self, context, router): is_ha = self._is_ha(router['router']) router['router']['ha'] = is_ha + if is_ha: + # we set the allocating status to hide it from the L3 agents + # until we have created all of the requisite interfaces/networks + router['router']['status'] = constants.ROUTER_STATUS_ALLOCATING + router_dict = super(L3_HA_NAT_db_mixin, self).create_router(context, router) @@ -453,11 +460,17 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin, context, router_db)[1] self._set_vr_id(context, router_db, ha_network) - self._notify_ha_interfaces_updated(context, router_db.id) + router_dict['ha_vr_id'] = router_db.extra_attributes.ha_vr_id + + self.schedule_router(context, router_dict['id']) + router_dict['status'] = self._update_router_db( + context, router_dict['id'], + {'status': constants.ROUTER_STATUS_ACTIVE})['status'] + self._notify_ha_interfaces_updated(context, router_db.id, + schedule_routers=False) except Exception: with excutils.save_and_reraise_exception(): self.delete_router(context, router_dict['id']) - router_dict['ha_vr_id'] = router_db.extra_attributes.ha_vr_id return router_dict def _update_router_db(self, context, router_id, data): @@ -492,19 +505,26 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin, if requested_ha_state is False: raise l3_ha.HAmodeUpdateOfDvrHaNotSupported() - with context.session.begin(subtransactions=True): - router_db = super(L3_HA_NAT_db_mixin, self)._update_router_db( - context, router_id, data) - - ha_not_changed = (requested_ha_state is None or - requested_ha_state == original_ha_state) - if ha_not_changed: - return router_db - + ha_changed = (requested_ha_state is not None and + requested_ha_state != original_ha_state) + if ha_changed: if router_db.admin_state_up: msg = _('Cannot change HA attribute of active routers. Please ' 'set router admin_state_up to False prior to upgrade.') raise n_exc.BadRequest(resource='router', msg=msg) + # set status to ALLOCATING so this router is no longer + # provided to agents while its interfaces are being re-configured. + # Keep in mind that if we want conversion to be hitless, this + # status cannot be used because agents treat hidden routers as + # deleted routers. + data['status'] = constants.ROUTER_STATUS_ALLOCATING + + with context.session.begin(subtransactions=True): + router_db = super(L3_HA_NAT_db_mixin, self)._update_router_db( + context, router_id, data) + + if not ha_changed: + return router_db ha_network = self.get_ha_network(context, router_db.tenant_id) @@ -524,10 +544,14 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin, ha_network = self._create_ha_interfaces_and_ensure_network( context, router_db)[1] self._set_vr_id(context, router_db, ha_network) - self._notify_ha_interfaces_updated(context, router_db.id) else: self._delete_ha_interfaces(context, router_db.id) - self._notify_ha_interfaces_updated(context, router_db.id) + + self.schedule_router(context, router_id) + router_db = super(L3_HA_NAT_db_mixin, self)._update_router_db( + context, router_id, {'status': constants.ROUTER_STATUS_ACTIVE}) + self._notify_ha_interfaces_updated(context, router_db.id, + schedule_routers=False) return router_db @@ -671,9 +695,7 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin, if interface: self._populate_mtu_and_subnets_for_ports(context, [interface]) - # we don't want to return HA routers without HA interfaces created yet - return [r for r in list(routers_dict.values()) - if not r.get('ha') or r.get(constants.HA_INTERFACE_KEY)] + return list(routers_dict.values()) @log_helpers.log_method_call def get_ha_sync_data_for_host(self, context, host, agent, diff --git a/neutron/scheduler/l3_agent_scheduler.py b/neutron/scheduler/l3_agent_scheduler.py index 13145bf7059..ebe13045532 100644 --- a/neutron/scheduler/l3_agent_scheduler.py +++ b/neutron/scheduler/l3_agent_scheduler.py @@ -87,6 +87,8 @@ class L3Scheduler(object): l3_db.Router.id == l3_agentschedulers_db.RouterL3AgentBinding.router_id) query = context.session.query(l3_db.Router.id).filter(no_agent_binding) + query = query.filter(l3_db.Router.status == + constants.ROUTER_STATUS_ACTIVE) unscheduled_router_ids = [router_id_[0] for router_id_ in query] if unscheduled_router_ids: return plugin.get_routers( @@ -102,7 +104,9 @@ class L3Scheduler(object): :returns: the list of routers to be scheduled """ if router_ids is not None: - routers = plugin.get_routers(context, filters={'id': router_ids}) + filters = {'id': router_ids, + 'status': [constants.ROUTER_STATUS_ACTIVE]} + routers = plugin.get_routers(context, filters=filters) return self._filter_unscheduled_routers(context, plugin, routers) else: return self._get_unscheduled_routers(context, plugin) diff --git a/neutron/tests/fullstack/test_l3_agent.py b/neutron/tests/fullstack/test_l3_agent.py index 7cadd4181a4..64bea300025 100644 --- a/neutron/tests/fullstack/test_l3_agent.py +++ b/neutron/tests/fullstack/test_l3_agent.py @@ -15,7 +15,6 @@ import functools from oslo_utils import uuidutils -import testtools from neutron.agent.l3 import agent as l3_agent from neutron.agent.l3 import namespaces @@ -73,7 +72,6 @@ class TestHAL3Agent(base.BaseFullStackTestCase): return ( agents['agents'][0]['ha_state'] != agents['agents'][1]['ha_state']) - @testtools.skip('bug/1550886') def test_ha_router(self): # TODO(amuller): Test external connectivity before and after a # failover, see: https://review.openstack.org/#/c/196393/ diff --git a/neutron/tests/functional/scheduler/test_l3_agent_scheduler.py b/neutron/tests/functional/scheduler/test_l3_agent_scheduler.py index 4ddf764f91d..b3b4c76c0f3 100644 --- a/neutron/tests/functional/scheduler/test_l3_agent_scheduler.py +++ b/neutron/tests/functional/scheduler/test_l3_agent_scheduler.py @@ -284,6 +284,7 @@ class L3AZSchedulerBaseTest(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): super(L3AZSchedulerBaseTest, self).setUp(plugin=core_plugin) self.l3_plugin = l3_router_plugin.L3RouterPlugin() + self.l3_plugin.router_scheduler = None self.adminContext = context.get_admin_context() self.adminContext.tenant_id = '_func_test_tenant_' diff --git a/neutron/tests/unit/db/test_l3_hamode_db.py b/neutron/tests/unit/db/test_l3_hamode_db.py index 8a6a406c37d..8a0ed7dc995 100644 --- a/neutron/tests/unit/db/test_l3_hamode_db.py +++ b/neutron/tests/unit/db/test_l3_hamode_db.py @@ -96,15 +96,6 @@ class L3HATestFramework(testlib_api.SqlTestCase): data['admin_state_up'] = admin_state return self.plugin._update_router_db(ctx, router_id, data) - def _bind_router(self, router_id): - with self.admin_ctx.session.begin(subtransactions=True): - agents_db = self.plugin.get_agents_db(self.admin_ctx) - self.plugin.router_scheduler._bind_ha_router_to_agents( - self.plugin, - self.admin_ctx, - router_id, - agents_db) - class L3HATestCase(L3HATestFramework): @@ -144,7 +135,6 @@ class L3HATestCase(L3HATestFramework): def test_get_ha_router_port_bindings(self): router = self._create_router() - self._bind_router(router['id']) bindings = self.plugin.get_ha_router_port_bindings( self.admin_ctx, [router['id']]) binding_dicts = [{'router_id': binding['router_id'], @@ -157,7 +147,6 @@ class L3HATestCase(L3HATestFramework): def test_get_l3_bindings_hosting_router_with_ha_states_ha_router(self): router = self._create_router() - self._bind_router(router['id']) self.plugin.update_routers_states( self.admin_ctx, {router['id']: 'active'}, self.agent1['host']) bindings = self.plugin.get_l3_bindings_hosting_router_with_ha_states( @@ -167,8 +156,10 @@ class L3HATestCase(L3HATestFramework): self.assertIn((self.agent2['id'], 'standby'), agent_ids) def test_get_l3_bindings_hosting_router_with_ha_states_agent_none(self): - router = self._create_router() - # Do not bind router to leave agents as None + with mock.patch.object(self.plugin, 'schedule_router'): + # Do not bind router to leave agents as None + router = self._create_router() + res = self.admin_ctx.session.query( l3_hamode_db.L3HARouterAgentPortBinding).filter( l3_hamode_db.L3HARouterAgentPortBinding.router_id == router['id'] @@ -194,7 +185,6 @@ class L3HATestCase(L3HATestFramework): def test_get_l3_bindings_hosting_router_with_ha_states_active_and_dead( self): router = self._create_router() - self._bind_router(router['id']) with mock.patch.object(agents_db.Agent, 'is_active', new_callable=mock.PropertyMock, return_value=False): @@ -206,6 +196,67 @@ class L3HATestCase(L3HATestFramework): agent_ids = [(agent[0]['id'], agent[1]) for agent in bindings] self.assertIn((self.agent1['id'], 'standby'), agent_ids) + def test_router_created_in_active_state(self): + router = self._create_router() + self.assertEqual(constants.ROUTER_STATUS_ACTIVE, router['status']) + + def test_router_update_stay_active(self): + router = self._create_router() + router['name'] = 'test_update' + router_updated = self.plugin._update_router_db(self.admin_ctx, + router['id'], router) + self.assertEqual(constants.ROUTER_STATUS_ACTIVE, + router_updated['status']) + + def test_allocating_router_hidden_from_sync(self): + r1, r2 = self._create_router(), self._create_router() + r1['status'] = constants.ROUTER_STATUS_ALLOCATING + self.plugin._update_router_db(self.admin_ctx, r1['id'], r1) + # store shorter name for readability + get_method = self.plugin._get_active_l3_agent_routers_sync_data + # r1 should be hidden + expected = [self.plugin.get_router(self.admin_ctx, r2['id'])] + self.assertEqual(expected, get_method(self.admin_ctx, None, None, + [r1['id'], r2['id']])) + # but once it transitions back, all is well in the world again! + r1['status'] = constants.ROUTER_STATUS_ACTIVE + self.plugin._update_router_db(self.admin_ctx, r1['id'], r1) + expected.append(self.plugin.get_router(self.admin_ctx, r1['id'])) + # just compare ids since python3 won't let us sort dicts + expected = sorted([r['id'] for r in expected]) + result = sorted([r['id'] for r in get_method( + self.admin_ctx, None, None, [r1['id'], r2['id']])]) + self.assertEqual(expected, result) + + def test_router_ha_update_allocating_then_active(self): + router = self._create_router() + _orig = self.plugin._delete_ha_interfaces + + def check_state(context, router_id): + self.assertEqual( + constants.ROUTER_STATUS_ALLOCATING, + self.plugin._get_router(context, router_id)['status']) + return _orig(context, router_id) + with mock.patch.object(self.plugin, '_delete_ha_interfaces', + side_effect=check_state) as ha_mock: + router = self._migrate_router(router['id'], ha=False) + self.assertTrue(ha_mock.called) + self.assertEqual(constants.ROUTER_STATUS_ACTIVE, + router['status']) + + def test_router_created_allocating_state_during_interface_create(self): + _orig = self.plugin._create_ha_interfaces + + def check_state(context, router_db, ha_network): + self.assertEqual(constants.ROUTER_STATUS_ALLOCATING, + router_db.status) + return _orig(context, router_db, ha_network) + with mock.patch.object(self.plugin, '_create_ha_interfaces', + side_effect=check_state) as ha_mock: + router = self._create_router() + self.assertTrue(ha_mock.called) + self.assertEqual(constants.ROUTER_STATUS_ACTIVE, router['status']) + def test_ha_router_create(self): router = self._create_router() self.assertTrue(router['ha']) @@ -330,7 +381,6 @@ class L3HATestCase(L3HATestFramework): def test_unbind_ha_router(self): router = self._create_router() - self._bind_router(router['id']) bound_agents = self.plugin.get_l3_agents_hosting_routers( self.admin_ctx, [router['id']]) @@ -365,7 +415,6 @@ class L3HATestCase(L3HATestFramework): def test_l3_agent_routers_query_interface(self): router = self._create_router() - self._bind_router(router['id']) routers = self.plugin.get_ha_sync_data_for_host(self.admin_ctx, self.agent1['host'], self.agent1) @@ -396,7 +445,6 @@ class L3HATestCase(L3HATestFramework): def _deployed_router_change_ha_flag(self, to_ha): router1 = self._create_router(ha=not to_ha) - self._bind_router(router1['id']) routers = self.plugin.get_ha_sync_data_for_host( self.admin_ctx, self.agent1['host'], self.agent1) router = routers[0] @@ -427,31 +475,6 @@ class L3HATestCase(L3HATestFramework): self._create_router() self.assertTrue(self.notif_m.called) - def test_allocating_router_hidden_from_sync(self): - self.plugin.supported_extension_aliases = [ - constants.L3_HA_MODE_EXT_ALIAS] - # simulate a router that is being allocated during - # the agent's synchronization - r1, r2 = self._create_router(), self._create_router() - self.plugin._delete_ha_interfaces(self.admin_ctx, r1['id']) - # store shorter name for readability - get_method = self.plugin._get_active_l3_agent_routers_sync_data - # r1 should be hidden - self.assertEqual([r2['id']], - [r['id'] for r in get_method(self.admin_ctx, - None, self.agent1, - [r1['id'], r2['id']])]) - # but once it transitions back, all is well in the world again! - rdb = self.plugin._get_router(self.admin_ctx, r1['id']) - self.plugin._create_ha_interfaces( - self.admin_ctx, rdb, self.plugin.get_ha_network( - self.admin_ctx, rdb.tenant_id)) - # just compare ids since python3 won't let us sort dicts - expected = sorted([r1['id'], r2['id']]) - result = sorted([r['id'] for r in get_method( - self.admin_ctx, None, self.agent1, [r1['id'], r2['id']])]) - self.assertEqual(expected, result) - def test_update_router_to_ha_notifies_agent(self): router = self._create_router(ha=False) self.notif_m.reset_mock() @@ -459,10 +482,8 @@ class L3HATestCase(L3HATestFramework): self.assertTrue(self.notif_m.called) def test_unique_vr_id_between_routers(self): - router1 = self._create_router() - router2 = self._create_router() - self._bind_router(router1['id']) - self._bind_router(router2['id']) + self._create_router() + self._create_router() routers = self.plugin.get_ha_sync_data_for_host( self.admin_ctx, self.agent1['host'], self.agent1) self.assertEqual(2, len(routers)) @@ -474,10 +495,8 @@ class L3HATestCase(L3HATestFramework): @mock.patch('neutron.db.l3_hamode_db.VR_ID_RANGE', new=set(range(1, 2))) def test_vr_id_unique_range_per_tenant(self): - router1 = self._create_router() - router2 = self._create_router(tenant_id=_uuid()) - self._bind_router(router1['id']) - self._bind_router(router2['id']) + self._create_router() + self._create_router(tenant_id=_uuid()) routers = self.plugin.get_ha_sync_data_for_host( self.admin_ctx, self.agent1['host'], self.agent1) self.assertEqual(2, len(routers)) @@ -527,10 +546,8 @@ class L3HATestCase(L3HATestFramework): self.assertEqual(allocs_before, allocs_after) def test_one_ha_router_one_not(self): - router1 = self._create_router(ha=False) - router2 = self._create_router() - self._bind_router(router1['id']) - self._bind_router(router2['id']) + self._create_router(ha=False) + self._create_router() routers = self.plugin.get_ha_sync_data_for_host( self.admin_ctx, self.agent1['host'], self.agent1) @@ -695,7 +712,6 @@ class L3HATestCase(L3HATestFramework): def test_get_active_host_for_ha_router(self): router = self._create_router() - self._bind_router(router['id']) self.assertEqual( None, self.plugin.get_active_host_for_ha_router( @@ -709,9 +725,7 @@ class L3HATestCase(L3HATestFramework): def test_update_routers_states(self): router1 = self._create_router() - self._bind_router(router1['id']) router2 = self._create_router() - self._bind_router(router2['id']) routers = self.plugin.get_ha_sync_data_for_host( self.admin_ctx, self.agent1['host'], self.agent1) @@ -731,9 +745,7 @@ class L3HATestCase(L3HATestFramework): def test_set_router_states_handles_concurrently_deleted_router(self): router1 = self._create_router() - self._bind_router(router1['id']) router2 = self._create_router() - self._bind_router(router2['id']) bindings = self.plugin.get_ha_router_port_bindings( self.admin_ctx, [router1['id'], router2['id']]) self.plugin.delete_router(self.admin_ctx, router1['id']) @@ -746,7 +758,6 @@ class L3HATestCase(L3HATestFramework): def test_update_routers_states_port_not_found(self): router1 = self._create_router() - self._bind_router(router1['id']) port = {'id': 'foo', 'device_id': router1['id']} with mock.patch.object(self.core_plugin, 'get_ports', return_value=[port]): @@ -891,7 +902,6 @@ class L3HATestCase(L3HATestFramework): def test_update_port_status_port_bingding_deleted_concurrently(self): router1 = self._create_router() - self._bind_router(router1['id']) states = {router1['id']: 'active'} with mock.patch.object(self.plugin, 'get_ha_router_port_bindings'): (self.admin_ctx.session.query( @@ -961,7 +971,6 @@ class L3HAModeDbTestCase(L3HATestFramework): interface_info = {'subnet_id': subnet['id']} router = self._create_router() - self._bind_router(router['id']) self.plugin.add_router_interface(self.admin_ctx, router['id'], interface_info) @@ -983,7 +992,6 @@ class L3HAModeDbTestCase(L3HATestFramework): interface_info = {'subnet_id': subnet['id']} router = self._create_router() - self._bind_router(router['id']) self.plugin.add_router_interface(self.admin_ctx, router['id'], interface_info) diff --git a/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py b/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py index c3d27202374..b1824ebfc65 100644 --- a/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py +++ b/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py @@ -1372,11 +1372,11 @@ class L3_HA_scheduler_db_mixinTestCase(L3HATestCaseMixin): # Mock scheduling so that the test can control it explicitly mock.patch.object(l3_hamode_db.L3_HA_NAT_db_mixin, '_notify_ha_interfaces_updated').start() - - router1 = self._create_ha_router() - router2 = self._create_ha_router() - router3 = self._create_ha_router(ha=False) - router4 = self._create_ha_router(ha=False) + with mock.patch.object(self.plugin, 'schedule_router'): + router1 = self._create_ha_router() + router2 = self._create_ha_router() + router3 = self._create_ha_router(ha=False) + router4 = self._create_ha_router(ha=False) # Agent 1 will host 0 routers, agent 2 will host 1, agent 3 will # host 2, and agent 4 will host 3. @@ -1800,12 +1800,11 @@ class L3AgentAZLeastRoutersSchedulerTestCase(L3HATestCaseMixin): def test_az_scheduler_ha_auto_schedule(self): cfg.CONF.set_override('max_l3_agents_per_router', 3) - r1 = self._create_ha_router(az_hints=['az1', 'az3']) self._set_l3_agent_admin_state(self.adminContext, self.agent2['id'], state=False) self._set_l3_agent_admin_state(self.adminContext, self.agent6['id'], state=False) - self.plugin.schedule_router(self.adminContext, r1['id']) + r1 = self._create_ha_router(az_hints=['az1', 'az3']) agents = self.plugin.get_l3_agents_hosting_routers( self.adminContext, [r1['id']]) self.assertEqual(2, len(agents)) From 93795a4bda47605d5616476b2a456772308aa3c3 Mon Sep 17 00:00:00 2001 From: Kevin Benton Date: Mon, 28 Mar 2016 14:14:15 -0700 Subject: [PATCH 44/51] Fix deprecation warning for external_network_bridge We only want this to warn when a deployer has set anything other than a blank string. The olso cfg would warn whenever it was set so it was incorrectly warning on the value we want operators to set it to. This changes the cfg option to not use deprecated for removal and the L3 agent config validation to emit a warning if its not set to the value we are suggesting. Change-Id: If533cf7c4c379be78f5a15073accaff7f65973ab Closes-Bug: #1563070 (cherry picked from 8382ac3717cf646145379456af94ce75000349a9) --- neutron/agent/common/config.py | 1 - neutron/agent/l3/agent.py | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/neutron/agent/common/config.py b/neutron/agent/common/config.py index d3594c4b81b..8c48b25b56d 100644 --- a/neutron/agent/common/config.py +++ b/neutron/agent/common/config.py @@ -84,7 +84,6 @@ AVAILABILITY_ZONE_OPTS = [ EXT_NET_BRIDGE_OPTS = [ cfg.StrOpt('external_network_bridge', default='br-ex', - deprecated_for_removal=True, help=_("Name of bridge used for external network " "traffic. This should be set to an empty value for the " "Linux Bridge. When this parameter is set, each L3 " diff --git a/neutron/agent/l3/agent.py b/neutron/agent/l3/agent.py index ddcb50da5f1..7735d4e9a01 100644 --- a/neutron/agent/l3/agent.py +++ b/neutron/agent/l3/agent.py @@ -263,6 +263,12 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, msg = _LE('An interface driver must be specified') LOG.error(msg) raise SystemExit(1) + if self.conf.external_network_bridge: + LOG.warning(_LW("Using an 'external_network_bridge' value other " + "than '' is deprecated. Any other values may " + "not be supported in the future. Note that the " + "default value is 'br-ex' so it must be " + "explicitly set to a blank value.")) if self.conf.ipv6_gateway: # ipv6_gateway configured. Check for valid v6 link-local address. From bf66cc6f74133cfe6c1ab75287d39814ac44b068 Mon Sep 17 00:00:00 2001 From: Clayton O'Neill Date: Thu, 24 Mar 2016 15:28:21 +0000 Subject: [PATCH 45/51] Don't disconnect br-int from phys br if connected When starting up, we don't want to delete the patch port between br-int and the physical bridges. In liberty the br-int bridge was changed to not tear down flows on startup, and change I9801b76829021c9a0e6358982e1136637634a521 will change the physical bridges to not tear down flows also. Without this patch the patch port is torn down and not reinstalled until after the initial flows are set back up. Partial-Bug: #1514056 Change-Id: I05bf5105a6f3acf6a313ce6799648a095cf8ec96 (cherry picked from commit a549f30fad93508bf9dfdcfb20cd522f7add27b0) --- .../openvswitch/agent/ovs_neutron_agent.py | 19 +++++++++++++------ .../functional/agent/test_l2_ovs_agent.py | 15 ++++++++++++++- .../agent/test_ovs_neutron_agent.py | 8 ++++++++ .../openvswitch/agent/test_ovs_tunnel.py | 9 ++++++++- 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py index 2e123a935bf..898aa6346de 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py @@ -1126,12 +1126,19 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin, if int_type == 'veth': self.int_br.delete_port(int_if_name) br.delete_port(phys_if_name) - # Create patch ports without associating them in order to block - # untranslated traffic before association - int_ofport = self.int_br.add_patch_port( - int_if_name, constants.NONEXISTENT_PEER) - phys_ofport = br.add_patch_port( - phys_if_name, constants.NONEXISTENT_PEER) + + # Setup int_br to physical bridge patches. If they already + # exist we leave them alone, otherwise we create them but don't + # connect them until after the drop rules are in place. + int_ofport = self.int_br.get_port_ofport(int_if_name) + if int_ofport == ovs_lib.INVALID_OFPORT: + int_ofport = self.int_br.add_patch_port( + int_if_name, constants.NONEXISTENT_PEER) + + phys_ofport = br.get_port_ofport(phys_if_name) + if phys_ofport == ovs_lib.INVALID_OFPORT: + phys_ofport = br.add_patch_port( + phys_if_name, constants.NONEXISTENT_PEER) self.int_ofports[physical_network] = int_ofport self.phys_ofports[physical_network] = phys_ofport diff --git a/neutron/tests/functional/agent/test_l2_ovs_agent.py b/neutron/tests/functional/agent/test_l2_ovs_agent.py index d81395fe323..1a3130d2413 100644 --- a/neutron/tests/functional/agent/test_l2_ovs_agent.py +++ b/neutron/tests/functional/agent/test_l2_ovs_agent.py @@ -226,7 +226,7 @@ class TestOVSAgent(base.OVSAgentTestFramework): self.agent.setup_physical_bridges(self.agent.bridge_mappings) time.sleep(0.25) - def test_assert_patch_port_ofports_dont_change(self): + def test_assert_br_int_patch_port_ofports_dont_change(self): # When the integration bridge is setup, it should reuse the existing # patch ports between br-int and br-tun. self.setup_agent_and_ports(port_dicts=[], create_tunnels=True) @@ -237,6 +237,19 @@ class TestOVSAgent(base.OVSAgentTestFramework): self.assertEqual(patch_int_ofport_before, self.agent.patch_int_ofport) self.assertEqual(patch_tun_ofport_before, self.agent.patch_tun_ofport) + def test_assert_br_phys_patch_port_ofports_dont_change(self): + # When the integration bridge is setup, it should reuse the existing + # patch ports between br-int and br-phys. + self.setup_agent_and_ports(port_dicts=[]) + patch_int_ofport_before = self.agent.int_ofports['physnet'] + patch_phys_ofport_before = self.agent.phys_ofports['physnet'] + + self.setup_agent_and_ports(port_dicts=[]) + self.assertEqual(patch_int_ofport_before, + self.agent.int_ofports['physnet']) + self.assertEqual(patch_phys_ofport_before, + self.agent.phys_ofports['physnet']) + def test_noresync_after_port_gone(self): '''This will test the scenario where a port is removed after listing it but before getting vif info about it. diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py index f485b2cd870..a1b3f1ed9f9 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py @@ -1073,6 +1073,8 @@ class TestOvsNeutronAgent(object): parent.attach_mock(int_br, 'int_br') phys_br.add_patch_port.return_value = "phy_ofport" int_br.add_patch_port.return_value = "int_ofport" + phys_br.get_port_ofport.return_value = ovs_lib.INVALID_OFPORT + int_br.get_port_ofport.return_value = ovs_lib.INVALID_OFPORT self.agent.setup_physical_bridges({"physnet1": "br-eth"}) expected_calls = [ mock.call.phys_br_cls('br-eth'), @@ -1084,8 +1086,10 @@ class TestOvsNeutronAgent(object): # Have to use __getattr__ here to avoid mock._Call.__eq__ # method being called mock.call.int_br.db_get_val().__getattr__('__eq__')('veth'), + mock.call.int_br.get_port_ofport('int-br-eth'), mock.call.int_br.add_patch_port('int-br-eth', constants.NONEXISTENT_PEER), + mock.call.phys_br.get_port_ofport('phy-br-eth'), mock.call.phys_br.add_patch_port('phy-br-eth', constants.NONEXISTENT_PEER), mock.call.int_br.drop_port(in_port='int_ofport'), @@ -1154,6 +1158,8 @@ class TestOvsNeutronAgent(object): parent.attach_mock(int_br, 'int_br') phys_br.add_patch_port.return_value = "phy_ofport" int_br.add_patch_port.return_value = "int_ofport" + phys_br.get_port_ofport.return_value = ovs_lib.INVALID_OFPORT + int_br.get_port_ofport.return_value = ovs_lib.INVALID_OFPORT self.agent.setup_physical_bridges({"physnet1": "br-eth"}) expected_calls = [ mock.call.phys_br_cls('br-eth'), @@ -1162,8 +1168,10 @@ class TestOvsNeutronAgent(object): mock.call.phys_br.setup_default_table(), mock.call.int_br.delete_port('int-br-eth'), mock.call.phys_br.delete_port('phy-br-eth'), + mock.call.int_br.get_port_ofport('int-br-eth'), mock.call.int_br.add_patch_port('int-br-eth', constants.NONEXISTENT_PEER), + mock.call.phys_br.get_port_ofport('phy-br-eth'), mock.call.phys_br.add_patch_port('phy-br-eth', constants.NONEXISTENT_PEER), mock.call.int_br.drop_port(in_port='int_ofport'), diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py index 4111551b3aa..bae6e001400 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_tunnel.py @@ -139,6 +139,8 @@ class TunnelTest(object): self.mock_int_bridge.add_port.return_value = self.MAP_TUN_INT_OFPORT self.mock_int_bridge.add_patch_port.side_effect = ( lambda tap, peer: self.ovs_int_ofports[tap]) + self.mock_int_bridge.get_port_ofport.return_value = ( + ovs_lib.INVALID_OFPORT) self.mock_int_bridge.get_vif_ports.return_value = [] self.mock_int_bridge.get_ports_attributes.return_value = [] self.mock_int_bridge.db_get_val.return_value = {} @@ -149,6 +151,8 @@ class TunnelTest(object): self.MAP_TUN_PHY_OFPORT) self.mock_map_tun_bridge.add_patch_port.return_value = ( self.MAP_TUN_PHY_OFPORT) + self.mock_map_tun_bridge.get_port_ofport.return_value = ( + ovs_lib.INVALID_OFPORT) self.mock_tun_bridge = self.ovs_bridges[self.TUN_BRIDGE] self.mock_tun_bridge.add_port.return_value = self.INT_OFPORT @@ -202,11 +206,14 @@ class TunnelTest(object): mock.call.create(), mock.call.setup_controllers(mock.ANY), mock.call.setup_default_table(), + mock.call.get_port_ofport('phy-%s' % self.MAP_TUN_BRIDGE), mock.call.add_patch_port('phy-%s' % self.MAP_TUN_BRIDGE, - constants.NONEXISTENT_PEER), ] + constants.NONEXISTENT_PEER), + ] self.mock_int_bridge_expected += [ mock.call.db_get_val('Interface', 'int-%s' % self.MAP_TUN_BRIDGE, 'type'), + mock.call.get_port_ofport('int-%s' % self.MAP_TUN_BRIDGE), mock.call.add_patch_port('int-%s' % self.MAP_TUN_BRIDGE, constants.NONEXISTENT_PEER), ] From eee9e58ed258a48c69effef121f55fdaa5b68bd6 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Tue, 9 Feb 2016 13:10:57 -0500 Subject: [PATCH 46/51] Add an option for WSGI pool size Neutron currently hardcodes the number of greenlets used to process requests in a process to 1000. As detailed in http://lists.openstack.org/pipermail/openstack-dev/2015-December/082717.html this can cause requests to wait within one process for available database connection while other processes remain available. By adding a wsgi_default_pool_size option functionally identical to that of Nova, we can lower the number of greenlets per process to be more in line with a typical max database connection pool size. DocImpact: a previously unused configuration value wsgi_default_pool_size is now used to affect the number of greenlets used by the server. The default number of greenlets also changes from 1000 to 100. Change-Id: I94cd2f9262e0f330cf006b40bb3c0071086e5d71 (cherry picked from commit 9d573387f1e33ce85269d3ed9be501717eed4807) --- neutron/wsgi.py | 4 ++-- .../config-wsgi-pool-size-a4c06753b79fee6d.yaml | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 releasenotes/notes/config-wsgi-pool-size-a4c06753b79fee6d.yaml diff --git a/neutron/wsgi.py b/neutron/wsgi.py index 5678c8d0244..febc5ec28b4 100644 --- a/neutron/wsgi.py +++ b/neutron/wsgi.py @@ -113,10 +113,10 @@ class WorkerService(worker.NeutronWorker): class Server(object): """Server class to manage multiple WSGI sockets and applications.""" - def __init__(self, name, num_threads=1000, disable_ssl=False): + def __init__(self, name, num_threads=None, disable_ssl=False): # Raise the default from 8192 to accommodate large tokens eventlet.wsgi.MAX_HEADER_LINE = CONF.max_header_line - self.num_threads = num_threads + self.num_threads = num_threads or CONF.wsgi_default_pool_size self.disable_ssl = disable_ssl # Pool for a greenthread in which wsgi server will be running self.pool = eventlet.GreenPool(1) diff --git a/releasenotes/notes/config-wsgi-pool-size-a4c06753b79fee6d.yaml b/releasenotes/notes/config-wsgi-pool-size-a4c06753b79fee6d.yaml new file mode 100644 index 00000000000..8b471057103 --- /dev/null +++ b/releasenotes/notes/config-wsgi-pool-size-a4c06753b79fee6d.yaml @@ -0,0 +1,12 @@ +--- +prelude: > + Support configuration of greenthreads pool for WSGI. +other: + - Operators may want to tune the ``max_overflow`` and + ``wsgi_default_pool_size`` configuration options according + to the investigations outlined in this `mailing list post + `_. + The default value of ``wsgi_default_pool_size`` inherits from + that of oslo.config, which is currently 100. This is + a change in default from the previous Neutron-specific + value of 1000. From b970ed5bdac60c0fa227f2fddaa9b842ba4f51a7 Mon Sep 17 00:00:00 2001 From: Kevin Benton Date: Fri, 8 Apr 2016 17:52:14 -0700 Subject: [PATCH 47/51] Clear DVR MAC on last agent deletion from host Once all agents are deleted from a host, the DVR MAC generated for that host should be deleted as well to prevent a buildup of pointless flows generated in the OVS agent for hosts that don't exist. Closes-Bug: #1568206 Change-Id: I51e736aa0431980a595ecf810f148ca62d990d20 (cherry picked from commit 92527c2de2afaf4862fddc101143e4d02858924d) --- neutron/callbacks/resources.py | 1 + neutron/db/agents_db.py | 7 +++++- neutron/db/dvr_mac_db.py | 30 ++++++++++++++++++++++ neutron/tests/unit/db/test_dvr_mac_db.py | 32 ++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 1 deletion(-) diff --git a/neutron/callbacks/resources.py b/neutron/callbacks/resources.py index 42d3d2fc470..753d7a51151 100644 --- a/neutron/callbacks/resources.py +++ b/neutron/callbacks/resources.py @@ -11,6 +11,7 @@ # under the License. # String literals representing core resources. +AGENT = 'agent' EXTERNAL_NETWORK = 'external_network' FLOATING_IP = 'floating_ip' PORT = 'port' diff --git a/neutron/db/agents_db.py b/neutron/db/agents_db.py index eda656d1959..3e4e82ad5e8 100644 --- a/neutron/db/agents_db.py +++ b/neutron/db/agents_db.py @@ -31,6 +31,9 @@ from sqlalchemy import sql from neutron._i18n import _, _LE, _LI, _LW from neutron.api.rpc.callbacks import version_manager from neutron.api.v2 import attributes +from neutron.callbacks import events +from neutron.callbacks import registry +from neutron.callbacks import resources from neutron.common import constants from neutron import context from neutron.db import api as db_api @@ -251,8 +254,10 @@ class AgentDbMixin(ext_agent.AgentPluginBase, AgentAvailabilityZoneMixin): return self._fields(res, fields) def delete_agent(self, context, id): + agent = self._get_agent(context, id) + registry.notify(resources.AGENT, events.BEFORE_DELETE, self, + context=context, agent=agent) with context.session.begin(subtransactions=True): - agent = self._get_agent(context, id) context.session.delete(agent) def update_agent(self, context, id, agent): diff --git a/neutron/db/dvr_mac_db.py b/neutron/db/dvr_mac_db.py index d43ddc14d42..3087c07efeb 100644 --- a/neutron/db/dvr_mac_db.py +++ b/neutron/db/dvr_mac_db.py @@ -22,6 +22,9 @@ from sqlalchemy import or_ from sqlalchemy.orm import exc from neutron._i18n import _, _LE +from neutron.callbacks import events +from neutron.callbacks import registry +from neutron.callbacks import resources from neutron.common import constants from neutron.common import exceptions as n_exc from neutron.common import utils @@ -60,9 +63,36 @@ class DistributedVirtualRouterMacAddress(model_base.BASEV2): mac_address = sa.Column(sa.String(32), nullable=False, unique=True) +def _delete_mac_associated_with_agent(resource, event, trigger, context, agent, + **kwargs): + host = agent['host'] + plugin = manager.NeutronManager.get_plugin() + if [a for a in plugin.get_agents(context, filters={'host': [host]}) + if a['id'] != agent['id']]: + # there are still agents on this host, don't mess with the mac entry + # until they are all deleted. + return + try: + with context.session.begin(subtransactions=True): + entry = (context.session.query(DistributedVirtualRouterMacAddress). + filter(DistributedVirtualRouterMacAddress.host == host). + one()) + context.session.delete(entry) + except exc.NoResultFound: + return + # notify remaining agents so they cleanup flows + dvr_macs = plugin.get_dvr_mac_address_list(context) + plugin.notifier.dvr_mac_address_update(context, dvr_macs) + + class DVRDbMixin(ext_dvr.DVRMacAddressPluginBase): """Mixin class to add dvr mac address to db_plugin_base_v2.""" + def __new__(cls, *args, **kwargs): + registry.subscribe(_delete_mac_associated_with_agent, + resources.AGENT, events.BEFORE_DELETE) + return super(DVRDbMixin, cls).__new__(cls) + @property def plugin(self): try: diff --git a/neutron/tests/unit/db/test_dvr_mac_db.py b/neutron/tests/unit/db/test_dvr_mac_db.py index e7c3e54c770..5b7ce40299c 100644 --- a/neutron/tests/unit/db/test_dvr_mac_db.py +++ b/neutron/tests/unit/db/test_dvr_mac_db.py @@ -16,11 +16,15 @@ import mock from oslo_config import cfg +from neutron.callbacks import events +from neutron.callbacks import registry +from neutron.callbacks import resources from neutron.common import constants from neutron import context from neutron.db import dvr_mac_db from neutron.extensions import dvr from neutron.extensions import portbindings +from neutron import manager from neutron.tests.unit.plugins.ml2 import test_plugin @@ -75,6 +79,34 @@ class DvrDbMixinTestCase(test_plugin.Ml2PluginV2TestCase): self.ctx, "foo_host_2") self.assertEqual(new_retries, f.call_count) + def test_mac_not_cleared_on_agent_delete_event_with_remaining_agents(self): + plugin = manager.NeutronManager.get_plugin() + self._create_dvr_mac_entry('host_1', 'mac_1') + self._create_dvr_mac_entry('host_2', 'mac_2') + agent1 = {'host': 'host_1', 'id': 'a1'} + agent2 = {'host': 'host_1', 'id': 'a2'} + with mock.patch.object(plugin, 'get_agents', return_value=[agent2]): + with mock.patch.object(plugin, 'notifier') as notifier: + registry.notify(resources.AGENT, events.BEFORE_DELETE, self, + context=self.ctx, agent=agent1) + mac_list = self.mixin.get_dvr_mac_address_list(self.ctx) + self.assertEqual(2, len(mac_list)) + self.assertFalse(notifier.dvr_mac_address_update.called) + + def test_mac_cleared_on_agent_delete_event(self): + plugin = manager.NeutronManager.get_plugin() + self._create_dvr_mac_entry('host_1', 'mac_1') + self._create_dvr_mac_entry('host_2', 'mac_2') + agent = {'host': 'host_1', 'id': 'a1'} + with mock.patch.object(plugin, 'notifier') as notifier: + registry.notify(resources.AGENT, events.BEFORE_DELETE, self, + context=self.ctx, agent=agent) + mac_list = self.mixin.get_dvr_mac_address_list(self.ctx) + self.assertEqual(1, len(mac_list)) + self.assertEqual('host_2', mac_list[0]['host']) + notifier.dvr_mac_address_update.assert_called_once_with( + self.ctx, mac_list) + def test_get_dvr_mac_address_list(self): self._create_dvr_mac_entry('host_1', 'mac_1') self._create_dvr_mac_entry('host_2', 'mac_2') From 1ffea42ccdc14b7a6162c1895bd8f2aae48d5dae Mon Sep 17 00:00:00 2001 From: OpenStack Proposal Bot Date: Mon, 18 Apr 2016 15:03:30 +0000 Subject: [PATCH 48/51] Updated from global requirements Change-Id: Icb27945b3f222af1d9ab2b62bf2169d82b6ae26c --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 4fb374a82bb..f0273cd24c0 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,7 +5,7 @@ hacking<0.11,>=0.10.0 cliff!=1.16.0,!=1.17.0,>=1.15.0 # Apache-2.0 coverage>=3.6 # Apache-2.0 -fixtures>=1.3.1 # Apache-2.0/BSD +fixtures<2.0,>=1.3.1 # Apache-2.0/BSD mock>=1.2 # BSD python-subunit>=0.0.18 # Apache-2.0/BSD requests-mock>=0.7.0 # Apache-2.0 From 643b4431606421b09d05eb0ccde130adbf88df64 Mon Sep 17 00:00:00 2001 From: OpenStack Proposal Bot Date: Tue, 19 Apr 2016 06:52:48 +0000 Subject: [PATCH 49/51] Imported Translations from Zanata For more information about this automatic import see: https://wiki.openstack.org/wiki/Translations/Infrastructure Change-Id: I52d7460b3265b5460b9089e1cc58624640dc7230 --- neutron/locale/de/LC_MESSAGES/neutron.po | 6 +- neutron/locale/es/LC_MESSAGES/neutron.po | 6 +- neutron/locale/fr/LC_MESSAGES/neutron.po | 929 +++++++++--------- neutron/locale/it/LC_MESSAGES/neutron.po | 9 +- neutron/locale/ja/LC_MESSAGES/neutron.po | 18 +- .../ko_KR/LC_MESSAGES/neutron-log-error.po | 6 +- .../ko_KR/LC_MESSAGES/neutron-log-info.po | 6 +- .../ko_KR/LC_MESSAGES/neutron-log-warning.po | 14 +- neutron/locale/ko_KR/LC_MESSAGES/neutron.po | 42 +- neutron/locale/neutron-log-error.pot | 194 ++-- neutron/locale/neutron-log-info.pot | 169 ++-- neutron/locale/neutron-log-warning.pot | 109 +- neutron/locale/neutron.pot | 33 +- neutron/locale/pt_BR/LC_MESSAGES/neutron.po | 6 +- neutron/locale/ru/LC_MESSAGES/neutron.po | 6 +- .../tr_TR/LC_MESSAGES/neutron-log-error.po | 14 +- .../tr_TR/LC_MESSAGES/neutron-log-info.po | 6 +- .../tr_TR/LC_MESSAGES/neutron-log-warning.po | 6 +- neutron/locale/tr_TR/LC_MESSAGES/neutron.po | 49 +- neutron/locale/zh_CN/LC_MESSAGES/neutron.po | 6 +- neutron/locale/zh_TW/LC_MESSAGES/neutron.po | 6 +- 21 files changed, 847 insertions(+), 793 deletions(-) diff --git a/neutron/locale/de/LC_MESSAGES/neutron.po b/neutron/locale/de/LC_MESSAGES/neutron.po index 53498bda3ae..a67934f036a 100644 --- a/neutron/locale/de/LC_MESSAGES/neutron.po +++ b/neutron/locale/de/LC_MESSAGES/neutron.po @@ -7,9 +7,9 @@ # Frank Kloeker , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.1.dev29\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-04-10 14:30+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-18 20:06+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/neutron/locale/es/LC_MESSAGES/neutron.po b/neutron/locale/es/LC_MESSAGES/neutron.po index ec7ea95304b..c7d207b867b 100644 --- a/neutron/locale/es/LC_MESSAGES/neutron.po +++ b/neutron/locale/es/LC_MESSAGES/neutron.po @@ -10,9 +10,9 @@ # Tom Cocozzello , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.1.dev29\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-04-10 14:30+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-18 20:06+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/neutron/locale/fr/LC_MESSAGES/neutron.po b/neutron/locale/fr/LC_MESSAGES/neutron.po index 29269ebef28..2e21a7fa687 100644 --- a/neutron/locale/fr/LC_MESSAGES/neutron.po +++ b/neutron/locale/fr/LC_MESSAGES/neutron.po @@ -7,22 +7,16 @@ # Maxime COQUEREL , 2014-2015 # Patrice LACHANCE , 2013 # Patrice LACHANCE , 2013 -# Cedric Savignan , 2015. #zanata -# Maxime Coquerel , 2015. #zanata -# OpenStack Infra , 2015. #zanata -# Tom Cocozzello , 2015. #zanata -# Angelique Pillal , 2016. #zanata -# Martine Marin , 2016. #zanata -# Tom Cocozzello , 2016. #zanata +# Sylvie Chesneau , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.1.dev29\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-04-10 14:30+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-18 20:06+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-03-25 05:16+0000\n" +"PO-Revision-Date: 2016-04-18 06:01+0000\n" "Last-Translator: Angelique Pillal \n" "Language: fr\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" @@ -56,7 +50,7 @@ msgstr "" #, python-format msgid "%(driver)s: Internal driver error." -msgstr "%(driver)s: erreur pilote interne." +msgstr "%(driver)s : erreur de pilote interne." #, python-format msgid "%(id)s is not a valid %(type)s identifier" @@ -79,8 +73,8 @@ msgid "" "%(method)s called with network settings %(current)s (original settings " "%(original)s) and network segments %(segments)s" msgstr "" -"%(method)s appelé avec les paramètres réseau %(current)s (paramètres " -"d'origine %(original)s) et segments de réseau %(segments)s" +"Méthode %(method)s appelée avec les paramètres réseau %(current)s " +"(paramètres d'origine %(original)s) et segments de réseau %(segments)s)" #, python-format msgid "" @@ -91,20 +85,21 @@ msgid "" "levels %(levels)s (original binding levels %(original_levels)s) on network " "%(network)s with segments to bind %(segments_to_bind)s" msgstr "" -"%(method)s appelée avec les paramètres de port %(current)s (paramètres " -"d'origine %(original)s) hôte %(host)s (hôte d'origine %(original_host)s) " -"type vif %(vif_type)s (type vif d'origine %(original_vif_type)s) détails vif " -"%(vif_details)s (détails vif d'origine %(original_vif_details)s) niveaux de " -"liaison %(levels)s (niveaux de liaison d'origine %(original_levels)s) sur le " -"réseau %(network)s avec des segments de liaison %(segments_to_bind)s" +"Méthode %(method)s appelée avec les paramètres de port %(current)s " +"(paramètres d'origine %(original)s) hôte %(host)s (hôte d'origine " +"%(original_host)s) type vif %(vif_type)s (type vif d'origine " +"%(original_vif_type)s) détails vif %(vif_details)s (détails vif d'origine " +"%(original_vif_details)s) niveaux de liaison %(levels)s (niveaux de liaison " +"d'origine %(original_levels)s) sur le réseau %(network)s avec des segments " +"de liaison %(segments_to_bind)s" #, python-format msgid "" "%(method)s called with subnet settings %(current)s (original settings " "%(original)s)" msgstr "" -"%(method)s a appelé les paramètres de sous-réseau %(current)s (paramètres " -"d'origine %(original)s)" +"Méthode %(method)s appelée avec les paramètres de sous-réseau %(current)s " +"(paramètres d'origine %(original)s)" #, python-format msgid "%(method)s failed." @@ -148,7 +143,7 @@ msgstr "%s interdit pour le réseau de fournisseurs de réseau local virtuel" #, python-format msgid "%s prohibited for flat provider network" -msgstr "%s interdit pour le réseau de fournisseurs non hiérarchique" +msgstr "%s interdit pour le réseau de fournisseurs centralisé" #, python-format msgid "%s prohibited for local provider network" @@ -190,13 +185,12 @@ msgstr "'%(data)s' est trop grand - ne doit pas être supérieur à '%(limit)d'" #, python-format msgid "'%(data)s' is too small - must be at least '%(limit)d'" -msgstr "'%(data)s' est trop petit - doit être au moins '%(limit)d'" +msgstr "'%(data)s' est trop petit - doit être au moins de '%(limit)d'" #, python-format msgid "'%(data)s' isn't a recognized IP subnet cidr, '%(cidr)s' is recommended" msgstr "" -"'%(data)s' n'est pas un routage CIDR de sous-réseau IP reconnu, '%(cidr)s' " -"est recommandé" +"'%(data)s' n'est pas un CIDR de sous-réseau IP reconnu, '%(cidr)s' recommandé" #, python-format msgid "'%(data)s' not a valid PQDN or FQDN. Reason: %(reason)s" @@ -210,7 +204,7 @@ msgstr "'%(host)s' n'est pas un serveur de noms valide. %(msg)s" #, python-format msgid "'%s' Blank strings are not permitted" -msgstr "'%s' les chaines de caractères vides ne sont pas autorisés" +msgstr "'%s' Les chaînes à blanc ne sont pas autorisées" #, python-format msgid "'%s' cannot be converted to boolean" @@ -218,11 +212,11 @@ msgstr "'%s' ne peut pas être converti en valeur booléenne." #, python-format msgid "'%s' cannot be converted to lowercase string" -msgstr "'%s' ne peut pas être converti en une chaîne minuscule " +msgstr "'%s' ne peut pas être converti en une chaîne en minuscules" #, python-format msgid "'%s' contains whitespace" -msgstr "'%s' contient des espaces blanc" +msgstr "'%s' contient des blancs" #, python-format msgid "'%s' exceeds the 255 character FQDN limit" @@ -231,8 +225,7 @@ msgstr "'%s' dépasse la limite de nom de domaine complet (255 caractères)" #, python-format msgid "'%s' is a FQDN. It should be a relative domain name" msgstr "" -"'%s' est un nom de domaine complet. Cela devrait être un nom de domaine " -"relatif" +"'%s' est un nom de domaine complet. Devrait être un nom de domaine relatif" #, python-format msgid "'%s' is not a FQDN" @@ -264,11 +257,11 @@ msgstr "'%s' n'est pas un type d'objet RBAC valide" #, python-format msgid "'%s' is not a valid UUID" -msgstr "'%s' n'est pas un identificateur unique universel valide." +msgstr "'%s' n'est pas un identificateur unique universel (UUID) valide." #, python-format msgid "'%s' is not a valid boolean value" -msgstr "'%s' n'est pas une valeur booléen valide " +msgstr "'%s' n'est pas une valeur booléenne valide " #, python-format msgid "'%s' is not a valid input" @@ -280,7 +273,7 @@ msgstr "'%s' n'est pas une chaîne valide." #, python-format msgid "'%s' is not an integer" -msgstr "'%s' n'est pas un entier." +msgstr "'%s' n'est pas un entier" #, python-format msgid "'%s' is not an integer or uuid" @@ -288,7 +281,7 @@ msgstr "'%s' n'est pas un entier ou un identificateur unique universel." #, python-format msgid "'%s' is not of the form =[value]" -msgstr "'%s'n'a pas la forme = [value]" +msgstr "'%s' n'a pas la forme = [valeur]" #, python-format msgid "'%s' is not supported for filtering" @@ -303,7 +296,7 @@ msgid "'%s' should be non-negative" msgstr "'%s' ne doit pas être négatif." msgid "'.' searches are not implemented" -msgstr "'.' recherches ne sont pas implémentées. " +msgstr "Les recherches de '.' ne sont pas implémentées. " #, python-format msgid "'module' object has no attribute '%s'" @@ -317,7 +310,7 @@ msgid "" "service to execute the command against." msgstr "" "(Obsolète. Utilisez '--subproject neutron-SERVICE' à la place.) Service " -"avancé sur lequel exécuter la commande. " +"avancé en fonction duquel exécuter la commande. " msgid "0 is not allowed as CIDR prefix length" msgstr "La longueur 0 n'est pas autorisée pour le préfixe CIDR" @@ -334,14 +327,14 @@ msgstr "Un pilote QoS doit être spécifié" msgid "A cidr must be specified in the absence of a subnet pool" msgstr "" -"Une valeur cidr doit être indiquée si aucun pool de sous-réseau n'est défini" +"Une valeur cidr doit être indiquée si aucun pool de sous-réseaux n'est défini" msgid "" "A decimal value as Vendor's Registered Private Enterprise Number as required " "by RFC3315 DUID-EN." msgstr "" "Valeur décimale telle que Numéro d'entreprise privé enregistré du " -"fournisseur comme requis par RFC3315 DUID-EN." +"fournisseur comme requis par la RFC3315 DUID-EN." #, python-format msgid "A default external network already exists: %(net_id)s." @@ -351,7 +344,7 @@ msgid "" "A default subnetpool for this IP family has already been set. Only one " "default may exist per IP family" msgstr "" -"Un pool de sous-réseau par défaut pour cette famille IP est déjà défini. Il " +"Un pool de sous-réseaux par défaut pour cette famille IP est déjà défini. Il " "ne peut y avoir qu'un seul pool par défaut par famille IP." msgid "" @@ -359,7 +352,7 @@ msgid "" "mapping is :. This mapping allows specifying a physical " "network MTU value that differs from the default segment_mtu value." msgstr "" -"Liste de mappages de réseaux physiques en valeurs d'unité de transmission " +"Liste de mappages de réseaux physiques à des valeurs d'unité de transmission " "maximale. Le format du mappage est :. Ce mappage permet de " "définir une valeur d'unité de transmission maximale de réseau physique " "différente de la valeur segment_mtu par défaut." @@ -377,10 +370,10 @@ msgstr "" "Neutron" msgid "Aborting periodic_sync_routers_task due to an error." -msgstr "Interruption de periodic_sync_routers_task en raison d'une erreur." +msgstr "Abandon de periodic_sync_routers_task en raison d'une erreur." msgid "Access to this resource was denied." -msgstr "L'accès a cette ressource était refusé" +msgstr "L'accès a cette ressource a été refusé." msgid "Action to be executed when a child process dies" msgstr "Action à exécuter quand un processus enfant meurt" @@ -390,13 +383,13 @@ msgid "" "comments to generated iptables rules that describe each rule's purpose. " "System must support the iptables comments module for addition of comments." msgstr "" -"Ajouter des commentaires aux règles iptables. Définir avec la valeur false " -"pour interdire l'ajout de commentaires aux règles iptables générées qui " -"décrivent l'objectif de chaque règle. Le système doit prendre en charge le " -"module de commentaires iptables pour l'ajout de commentaires." +"Ajouter des commentaires aux règles iptables. Définir sur false pour " +"interdire l'ajout de commentaires aux règles iptables générées qui décrivent " +"l'objectif de chaque règle. Le système doit prendre en charge le module de " +"commentaires iptables pour l'ajout de commentaires." msgid "Address not present on interface" -msgstr "Une adresse n'est pas présente sur l'interface" +msgstr "L'adresse n'est pas présente sur l'interface" #, python-format msgid "Address scope %(address_scope_id)s could not be found" @@ -412,7 +405,7 @@ msgid "Adds external network attribute to network resource." msgstr "Ajoute l'attribut de réseau externe à la ressource du réseau." msgid "Adds test attributes to core resources." -msgstr "Ajoute les attributs de test aux ressources principales." +msgstr "Ajoute des attributs de test aux ressources principales." #, python-format msgid "Agent %(id)s could not be found" @@ -441,7 +434,7 @@ msgstr "" #, python-format msgid "Agent updated: %(payload)s" -msgstr "Mise à jour de l'agent: %(payload)s" +msgstr "Mise à jour de l'agent : %(payload)s" #, python-format msgid "" @@ -449,26 +442,27 @@ msgid "" msgstr "Agent introuvable avec agent_type=%(agent_type)s et host=%(host)s" msgid "Allow auto scheduling networks to DHCP agent." -msgstr "Autorise la planification automatique des réseaux de l'agent DHCP." +msgstr "Autoriser la planification automatique des réseaux pour l'agent DHCP." msgid "Allow auto scheduling of routers to L3 agent." -msgstr "Autorise la planification automatique des routeurs vers l'agent L3." +msgstr "Autoriser la planification automatique des routeurs vers l'agent L3." msgid "" "Allow overlapping IP support in Neutron. Attention: the following parameter " "MUST be set to False if Neutron is being used in conjunction with Nova " "security groups." msgstr "" -"Autoriser la prise en charge IP du chevauchement dans Neutron. Attention : " -"le paramètre ci-après DOIT être défini sur False si Neutron est utilisé " -"conjointement avec des groupes de sécurité Nova." +"Autoriser la prise en charge du chevauchement d'IP dans Neutron. " +"Attention : le paramètre ci-après DOIT être défini sur False si Neutron est " +"utilisé conjointement avec des groupes de sécurité Nova." msgid "Allow running metadata proxy." msgstr "Autorisez le proxy de métadonnées en cours d'exécution." msgid "Allow sending resource operation notification to DHCP agent" msgstr "" -"Autoriser l'envoi de notifications d'opérations de ressources à l'agent DHCP" +"Autoriser l'envoi à l'agent DHCP de notifications d'opérations sur les " +"ressources" msgid "Allow the creation of PTR records" msgstr "Autoriser la création d'enregistrements PTR" @@ -477,15 +471,15 @@ msgid "Allow the usage of the bulk API" msgstr "Autoriser l'utilisation de l'API de traitement en bloc" msgid "Allow the usage of the pagination" -msgstr "Autoriser l'utilisation de la mise en page" +msgstr "Autoriser l'utilisation de la pagination" msgid "Allow the usage of the sorting" msgstr "Autoriser l'utilisation du tri" msgid "Allow to perform insecure SSL (https) requests to nova metadata" msgstr "" -"Permet d'effectuer des requêtes (https) non sécurisées aux métadonnées de " -"nova" +"Permet d'effectuer des demandes SSL (https) non sécurisées sur les " +"métadonnées nova" msgid "Allowed address pairs must be a list." msgstr "Les paires d'adresses autorisées doivent figurer dans une liste. " @@ -540,15 +534,15 @@ msgid "" "neutron.ml2.extension_drivers namespace. For example: extension_drivers = " "port_security,qos" msgstr "" -"An ordered list of extension driver entrypoints to be loaded from the " -"neutron.ml2.extension_drivers namespace. For example: extension_drivers = " -"port_security,qos" +"Liste ordonnée des points d'entrée de pilote d'extension à charger à partir " +"de l'espace de nom neutron.ml2.extension_drivers namespace. Par exemple : " +"extension_drivers = port_security,qos" msgid "" "An ordered list of networking mechanism driver entrypoints to be loaded from " "the neutron.ml2.mechanism_drivers namespace." msgstr "" -"Liste ordonnée de points d'entrée de pilote de mécanisme à charger à partir " +"Liste ordonnée des points d'entrée de pilote de mécanisme à charger à partir " "de l'espace de nom neutron.ml2.mechanism_drivers." msgid "An unexpected internal error occurred." @@ -562,7 +556,8 @@ msgstr "Le processus Async n'a pas été relancé" #, python-format msgid "Attribute '%s' not allowed in POST" -msgstr "Attribut '%s non autorisé dans l'autotest à la mise sous tension" +msgstr "" +"Attribut '%s non autorisé dans l'autotest à la mise sous tension (POST)" #, python-format msgid "Authentication type not supported. Requested type=%(auth_type)s." @@ -574,13 +569,13 @@ msgstr "" "URL d'autorisation pour la connexion au réseau désigné dans un contexte admin" msgid "Automatically remove networks from offline DHCP agents." -msgstr "Supprime automatiquement les réseaux des agents DHCP hors ligne." +msgstr "Retirer automatiquement les réseaux des agents DHCP hors ligne." msgid "" "Automatically reschedule routers from offline L3 agents to online L3 agents." msgstr "" "Replanifier automatiquement les routeurs pour qu'ils passent d'agents L3 " -"hors connexion aux agents L3 connectés." +"hors connexion à des agents L3 connectés." msgid "Availability zone of this node" msgstr "Zone de disponibilité du noeud" @@ -598,7 +593,7 @@ msgid "" "%(speaker_as)d not added yet." msgstr "" "Homologue BGP %(peer_ip)s pour remote_as=%(remote_as)s, en cours d'exécution " -"pour routeur BGP %(speaker_as)d non encore ajouté." +"pour routeur BGP %(speaker_as)d pas encore ajouté." #, python-format msgid "" @@ -613,7 +608,7 @@ msgstr "" msgid "" "BGP Speaker for local_as=%(local_as)s with router_id=%(rtid)s not added yet." msgstr "" -"Routeur BGP pour local_as=%(local_as)s avec router_id=%(rtid)s non encore " +"Routeur BGP pour local_as=%(local_as)s avec router_id=%(rtid)s pas encore " "ajouté." #, python-format @@ -647,15 +642,15 @@ msgid "BGP speaker driver class to be instantiated." msgstr "Classe de pilote de routeur BGP à instancier." msgid "Backend does not support VLAN Transparency." -msgstr "Le backend ne prend pas en charge la transparence VLAN." +msgstr "Le back-end ne prend pas en charge la transparence de VLAN." #, python-format msgid "" "Bad prefix or mac format for generating IPv6 address by EUI-64: %(prefix)s, " "%(mac)s:" msgstr "" -"Mauvais type de préfixe ou mauvais format d'adresse mac pour générer une " -"adresse IPv6 par EUI-64: %(prefix)s, %(mac)s:" +"Type de préfixe ou format d'adresse MAC incorrect pour générer une adresse " +"IPv6 par EUI-64 : %(prefix)s, %(mac)s :" #, python-format msgid "Bad prefix type for generate IPv6 address by EUI-64: %s" @@ -693,8 +688,8 @@ msgstr "Le corps contient des données non valides" msgid "Both network_id and router_id are None. One must be provided." msgstr "" -"Les paramètres Both network_id et router_id sont définis sur None. L'un des " -"deux doit obligatoirement être fourni." +"Les paramètres network_id et router_id sont tous deux définis sur None. L'un " +"des deux doit obligatoirement être fourni." #, python-format msgid "Bridge %(bridge)s does not exist." @@ -702,10 +697,10 @@ msgstr "Le pont %(bridge)s n'existe pas." #, python-format msgid "Bridge %s does not exist" -msgstr "Le pont %s est inexistant." +msgstr "Le pont %s n'existe pas" msgid "Bulk operation not supported" -msgstr "Opération globale non prise en charge" +msgstr "Opération groupée non prise en charge" msgid "CIDR to monitor" msgstr "CIDR à surveiller" @@ -729,7 +724,7 @@ msgstr "" msgid "Cannot add floating IP to port on subnet %s which has no gateway_ip" msgstr "" "Impossible d'ajouter une adresse IP flottante au port sur le sous-réseau %s " -"qui n'a pas d'adresse IP passerelle" +"qui n'a pas d'adresse IP passerelle (gateway_ip)" #, python-format msgid "Cannot add multiple callbacks for %(resource_type)s" @@ -744,7 +739,7 @@ msgstr "" msgid "Cannot allocate requested subnet from the available set of prefixes" msgstr "" "Impossible d'allouer le sous-réseau demandé à partir de l'ensemble de " -"préfixes disponibles" +"préfixes disponible" #, python-format msgid "" @@ -753,7 +748,7 @@ msgid "" "floating IP on external network %(net_id)s." msgstr "" "Impossible d'associer l'adresse IP flottante %(floating_ip_address)s " -"(%(fip_id)s) avec le port %(port_id)s en utilisant l'adresse IP fixe " +"(%(fip_id)s) aulport %(port_id)s en utilisant l'adresse IP fixe " "%(fixed_ip)s, car cette adresse IP fixe a déjà une adresse IP flottante sur " "le réseau externe %(net_id)s." @@ -781,7 +776,7 @@ msgstr "" "ce port appartient à un locataire différent." msgid "Cannot create resource for another tenant" -msgstr "Impossible de créer une ressource pour un autre titulaire" +msgstr "Impossible de créer une ressource pour un autre locataire" msgid "Cannot disable enable_dhcp with ipv6 attributes set" msgstr "Impossible de désactiver enable_dhcp avec des attributs ipv6 définis" @@ -792,7 +787,7 @@ msgstr "Impossible de trouver %(table)s avec %(col)s=%(match)s" #, python-format msgid "Cannot handle subnet of type %(subnet_type)s" -msgstr "Impossible de traiter le sous-réseau de type %(subnet_type)s" +msgstr "Impossible de gérer le sous-réseau de type %(subnet_type)s" msgid "Cannot have multiple IPv4 subnets on router port" msgstr "Impossible d'avoir plusieurs sous-réseaux IPv4 sur le port de routeur" @@ -810,7 +805,7 @@ msgstr "" msgid "" "Cannot host distributed router %(router_id)s on legacy L3 agent %(agent_id)s." msgstr "" -"Impossible d'héberger un routeur distribué %(router_id)s sur l'agent L3 " +"Impossible d'héberger le routeur distribué %(router_id)s sur l'agent L3 " "existant %(agent_id)s." msgid "Cannot match priority on flow deletion or modification" @@ -820,13 +815,14 @@ msgstr "" msgid "Cannot mix IPv4 and IPv6 prefixes in a subnet pool." msgstr "" -"Impossible d'associer les préfixes IPv4 et IPv6 dans un pool de sous-réseau." +"Impossible d'utiliser les préfixes IPv4 et IPv6 dans un même pool de sous-" +"réseaux." msgid "Cannot specify both --service and --subproject." -msgstr "Impossible de spécifier le service et le sous-projet. " +msgstr "Impossible de spécifier --service et --subproject." msgid "Cannot specify both subnet-id and port-id" -msgstr "Impossible de spécifier l'ID sous-réseau et l'ID port" +msgstr "Impossible de spécifier à la fois l'ID sous-réseau et l'ID port" msgid "Cannot understand JSON" msgstr "Impossible de comprendre JSON" @@ -858,40 +854,40 @@ msgid "Check ebtables installation" msgstr "Vérifier l'installation ebtables " msgid "Check for ARP header match support" -msgstr "Vérifier le support de correspondance d'en-tête ARP" +msgstr "Vérifier la prise en charge de correspondance d'en-tête ARP" msgid "Check for ARP responder support" -msgstr "Vérifier le support de programme de réponse ARP" +msgstr "Vérifier la prise en charge de programme de réponse ARP" msgid "Check for ICMPv6 header match support" -msgstr "Vérifier le support de correspondance d'en-tête ICMPv6" +msgstr "Vérifier la prise en charge de correspondance d'en-tête ICMPv6" msgid "Check for OVS Geneve support" -msgstr "Vérifier le support OVS Geneve" +msgstr "Vérifier la prise en charge OVS Geneve" msgid "Check for OVS vxlan support" -msgstr "Vérifier le support OVS vxlan" +msgstr "Vérifier la prise en charge OVS vxlan" msgid "Check for VF management support" -msgstr "Vérifier le support de gestion VF" +msgstr "Vérifier la prise en charge de gestion VF" msgid "Check for iproute2 vxlan support" -msgstr "Vérifier le support iproute2 vxlan" +msgstr "Vérifier la prise en charge iproute2 vxlan" msgid "Check for nova notification support" -msgstr "Vérifier le support de notification de Nova" +msgstr "Vérifier la prise en charge de notification Nova" msgid "Check for patch port support" -msgstr "Vérifier le support de port de correctif" +msgstr "Vérifier la prise en charge de port de correctif" msgid "Check ip6tables installation" -msgstr "Consultez l'installation ip6tables" +msgstr "Vérifer l'installation ip6tables" msgid "Check ipset installation" msgstr "Vérifier l'installation ipset" msgid "Check keepalived IPv6 support" -msgstr "Vérifier le support de keepalived IPv6" +msgstr "Vérifier la prise en charge keepalived IPv6" msgid "Check minimal dibbler version" msgstr "Vérifier la version minimale de dibbler" @@ -900,30 +896,30 @@ msgid "Check minimal dnsmasq version" msgstr "Vérifier la version minimale de dnsmasq" msgid "Check netns permission settings" -msgstr "Vérifier les autorisations netns" +msgstr "Vérifier les paramètres d'autorisation netns" msgid "Check ovs conntrack support" -msgstr "Consultez le support ovs conntrack" +msgstr "Vérifier la prise en charge ovs conntrack" msgid "Check ovsdb native interface support" -msgstr "Consulter le support d'interface native ovsdb" +msgstr "Vérifer la prise en charge d'interface native ovsdb" #, python-format msgid "" "Cidr %(subnet_cidr)s of subnet %(subnet_id)s overlaps with cidr %(cidr)s of " "subnet %(sub_id)s" msgstr "" -"Le routage CIDR %(subnet_cidr)s du sous-réseau %(subnet_id)s chevauche le " -"routage CIDR %(cidr)s du sous-réseau %(sub_id)s" +"Le CIDR %(subnet_cidr)s du sous-réseau %(subnet_id)s chevauche le CIDR " +"%(cidr)s du sous-réseau %(sub_id)s" msgid "Class not found." -msgstr "Classe non trouvé." +msgstr "Classe introuvable." msgid "Cleanup resources of a specific agent type only." msgstr "Ressources de nettoyage d'un type d'agent spécifique uniquement." msgid "Client certificate for nova metadata api server." -msgstr "Certificat client pour le serveur d'API des métadonnées nova." +msgstr "Certificat client pour le serveur d'API de métadonnées nova." msgid "" "Comma-separated list of : tuples, mapping " @@ -935,8 +931,8 @@ msgid "" msgstr "" "Liste des uplets :, séparés par des " "virgules, qui mappent network_device à la liste de fonctions spécifique à un " -"nœud d'agent des fonctions virtuelles qui ne doivent pas être utilisées pour " -"une mise en réseau virtuelle. vfs_to_exclude est une liste de fonctions " +"noeud d'agent des fonctions virtuelles qui ne doivent pas être utilisées " +"pour une mise en réseau virtuelle. vfs_to_exclude est une liste de fonctions " "virtuelles, séparées par des virgules, à exclure de network_device. " "network_device dans le mappage doit figurer dans la liste " "physical_device_mappings." @@ -954,7 +950,7 @@ msgid "" msgstr "" "Liste des uplets :, séparés par des virgules, qui " "mappent les noms de réseau physique au noms de pont Open vSwitch spécifiques " -"à un nœud d'agent à utiliser pour les réseaux centralisés et VLAN. La " +"à un noeud d'agent à utiliser pour les réseaux centralisés et VLAN. La " "longueur des noms de pont ne doit pas dépasser 11. Chaque pont doit exister " "et doit comporter une interface réseau physique configurée en tant que port. " "Tous les réseaux physiques configurés sur le serveur doivent avoir des " @@ -971,7 +967,7 @@ msgid "" msgstr "" "Liste des uplets : séparés par des " "virgules, qui mappent les noms de réseau physique aux interfaces d'unité " -"réseau physiques spécifiques à un nœud d'agent de la fonction physique SR-" +"réseau physiques spécifiques à un noeud d'agent de la fonction physique SR-" "IOV à utiliser pour les réseaux VLAN. Tous les réseaux physiques répertoriés " "dans network_vlan_ranges sur le serveur doivent avoir des mappages aux " "interfaces appropriées sur chaque agent." @@ -985,7 +981,7 @@ msgid "" msgstr "" "Liste des uplets : séparés par des " "virgules qui mappent les noms de réseau physique aux interfaces de réseau " -"physique spécifiques à un nœud d'agent à utiliser pour les réseaux " +"physique spécifiques à un noeud d'agent à utiliser pour les réseaux " "centralisés et VLAN. Tous les réseaux physiques répertoriés dans " "network_vlan_ranges sur le serveur doivent avoir des mappages aux interfaces " "appropriées sur chaque agent." @@ -1044,9 +1040,9 @@ msgid "" "should be false when using no security groups or using the nova security " "group API." msgstr "" -"Indique si l'API de groupe de sécurité neutron est activée sur le serveur. " -"Elle doit être false si aucun groupe de sécurité n'est utilisé ou en cas " -"d'utilisation de l'API du groupe de sécurité neutron." +"Contrôle si l'API de groupe de sécurité neutron est activée sur le serveur. " +"La valeur doit être false si aucun groupe de sécurité n'est utilisé ou en " +"cas d'utilisation de l'API du groupe de sécurité neutron." #, python-format msgid "Could not bind to %(host)s:%(port)s after trying for %(time)d seconds" @@ -1059,7 +1055,7 @@ msgid "Could not connect to %s" msgstr "Impossible de se connecter à %s" msgid "Could not deserialize data" -msgstr "Impossible de désérialiser des données" +msgstr "Impossible de désérialiser les données" #, python-format msgid "Could not retrieve schema from %(conn)s: %(err)s" @@ -1070,8 +1066,8 @@ msgid "" "Current gateway ip %(ip_address)s already in use by port %(port_id)s. Unable " "to update." msgstr "" -"L'adresse IP de la passerelle en cours %(ip_address)s est déjà en cours " -"d'utilisation par le port %(port_id)s. Impossible de mettre à jour" +"L'adresse IP de la passerelle en cours %(ip_address)s est déjà utilisée par " +"le port %(port_id)s. Mise à jour impossible." msgid "Currently update of HA mode for a DVR/HA router is not supported." msgstr "" @@ -1109,8 +1105,8 @@ msgid "" "DHCP lease duration (in seconds). Use -1 to tell dnsmasq to use infinite " "lease times." msgstr "" -"Durée de bail DHCP (en secondes). Utiliser -1 pour ordonner dnsmasq pour " -"utiliser des durées de bail illimitées." +"Durée de bail DHCP (en secondes). Utiliser -1 pour indiquer à dnsmasq " +"d'utiliser des durées de bail illimitées." msgid "" "DVR deployments for VXLAN/GRE/Geneve underlays require L2-pop to be enabled, " @@ -1136,14 +1132,14 @@ msgid "" "space. This option is deprecated for removal in the N release." msgstr "" "Pool de sous-réseau IPv4 par défaut à utiliser pour l'allocation CIDR de " -"sous-réseau automatique. Indique par UUID le pool à utiliser dans le cas où " -"la création d'un sous-réseau est appelée sans ID de pool de sous-réseau. Si " -"ce paramètre n'est pas défini, aucun pool ne sera utilisé sauf s'il est " +"sous-réseau automatique. Indique par UUID le pool à utiliser quand la " +"création d'un sous-réseau est appelée sans ID de pool de sous-réseau. Si ce " +"paramètre n'est pas défini, aucun pool ne sera utilisé à moins d'être " "indiqué de manière explicite lors de la création de sous-réseau. Si aucun " "pool n'est utilisé, un CIDR doit être transmis pour la création d'un sous-" "réseau, et ce dernier ne sera alloué depuis aucun pool ; il sera considéré " "comme faisant partie de l'espace d'adresse privé du locataire. Cette option " -"est obsolète et va être retirée dans la version N." +"est obsolète et sera retirée dans la version N." msgid "" "Default IPv6 subnet pool to be used for automatic subnet CIDR allocation. " @@ -1152,11 +1148,11 @@ msgid "" "default_ipv4_subnet_pool for more information. This option is deprecated for " "removal in the N release." msgstr "" -"Default IPv6 subnet pool to be used for automatic subnet CIDR allocation. " -"Specifies by UUID the pool to be used in case where creation of a subnet is " -"being called without a subnet pool ID. See the description for " -"default_ipv4_subnet_pool for more information. This option is deprecated for " -"removal in the N release." +"Pool de sous-réseau IPv6 par défaut à utiliser pour l'allocation CIDR de " +"sous-réseau automatique. Indique par UUID le pool à utiliser quand la " +"création d'un sous-réseau est appelée sans ID pool de sous-réseau. Voir la " +"description de default_ipv4_subnet_pool pour plus d'informations. Cette " +"option est obsolète et sera retirée dans la version N." msgid "Default driver to use for quota checks" msgstr "Pilote par défaut à utiliser pour les vérifications de quota" @@ -1176,9 +1172,9 @@ msgstr "" "fournisseur n'est spécifié. La valeur par défaut None signifie que si des " "attributs de fournisseur ne sont pas spécifiés lors de la création de " "réseaux externes, ces derniers prennent le même type que les réseaux " -"locataires. Les valeurs autorisées pour l'option de config " +"locataires. Les valeurs autorisées pour l'option de configuration " "external_network_type dépendent des valeurs de type de réseau configurées " -"dans l'option de config type_drivers. " +"dans l'option de configuration type_drivers. " msgid "" "Default number of RBAC entries allowed per tenant. A negative value means " @@ -1191,7 +1187,7 @@ msgid "" "Default number of resource allowed per tenant. A negative value means " "unlimited." msgstr "" -"Nombre de ressources par défaut autorisées par le locataire. Une valeur " +"Nombre par défaut de ressources autorisées par locataire. Une valeur " "négative signifie illimité." msgid "Default security group" @@ -1210,9 +1206,9 @@ msgid "" msgstr "" "Valeur par défaut des suggestions de zone de disponibilité. Les " "planificateurs de zone de disponibilité utilisent cette valeur lorsque le " -"paramètre resources availability_zone_hints est à blanc. Plusieurs zones de " -"disponibilité peuvent être indiquées en les séparant par une virgule. Cette " -"valeur peut être vide. Dans ce cas, même si le paramètre " +"paramètre availability_zone_hints de ressources est à blanc. Plusieurs zones " +"de disponibilité peuvent être indiquées en les séparant par une virgule. " +"Cette valeur peut être vide. Dans ce cas, même si le paramètre " "availability_zone_hints d'une ressource est à blanc, la zone de " "disponibilité est prise en compte pour la haute disponibilité lors de la " "planification de la ressource." @@ -1239,7 +1235,7 @@ msgstr "" "lors de son redémarrage" msgid "Delete the namespace by removing all devices." -msgstr "Supprimez l'espace de nom en supprimant toutes les unités." +msgstr "Supprimez l'espace de nom en retirant toutes les unités." #, python-format msgid "Deleting port %s" @@ -1250,30 +1246,28 @@ msgid "Deployment error: %(reason)s." msgstr "Erreur de déploiement : %(reason)s." msgid "Destroy IPsets even if there is an iptables reference." -msgstr "Détruire les IPsets même s'il y a une référence iptables." +msgstr "Destruction des IPsets même s'il existe une référence iptables." msgid "Destroy all IPsets." msgstr "Destruction de tous les IPsets." #, python-format msgid "Device %(dev_name)s in mapping: %(mapping)s not unique" -msgstr "Périphérique %(dev_name)s non unique dans le mappage '%(mapping)s'" +msgstr "Unité %(dev_name)s non unique dans le mappage '%(mapping)s'" #, python-format msgid "Device '%(device_name)s' does not exist." msgstr "L'unité '%(device_name)s' n'existe pas." msgid "Device has no virtual functions" -msgstr "L'unité n'a aucune fonction virtuelle" +msgstr "L'unité ne possède pas de fonction virtuelle" #, python-format msgid "Device name %(dev_name)s is missing from physical_device_mappings" -msgstr "" -"Le nom de périphérique %(dev_name)s est manquant dans " -"physical_device_mappings" +msgstr "Le nom d'unité %(dev_name)s est manquant dans physical_device_mappings" msgid "Device not found" -msgstr "Equipement non trouvé" +msgstr "Unité introuvable." #, python-format msgid "" @@ -1303,21 +1297,21 @@ msgstr "La rétromigration n'est plus prise en charge" #, python-format msgid "Driver %s is not unique across providers" -msgstr "Le pilote %s n'est pas unique entre les fournisseurs" +msgstr "Le pilote %s n'est pas unique parmi les fournisseurs" msgid "Driver for external DNS integration." msgstr "Pilote pour intégration DNS externe." msgid "Driver for security groups firewall in the L2 agent" -msgstr "" -"Pilote pour le pare-feu de groupes de sécurité dans l'agent de niveau 2" +msgstr "Pilote pour le pare-feu de groupes de sécurité dans l'agent L2" msgid "Driver to use for scheduling network to DHCP agent" -msgstr "Pilote à utiliser pour la planification du réseau de l'agent DHCP" +msgstr "Pilote à utiliser pour la planification du réseau pour l'agent DHCP" msgid "Driver to use for scheduling router to a default L3 agent" msgstr "" -"Pilote à utiliser pour la planification du routeur de l'agent L3 par défaut" +"Pilote à utiliser pour la planification du routeur pour un agent L3 par " +"défaut" msgid "" "Driver used for ipv6 prefix delegation. This needs to be an entry point " @@ -1356,7 +1350,8 @@ msgstr "Règle de mesure en double dans POST." msgid "Duplicate Security Group Rule in POST." msgstr "" -"Règle de groupe de sécurité en double dans l'autotest à la mise sous tension." +"Règle de groupe de sécurité en double dans l'autotest à la mise sous tension " +"(POST)." msgid "Duplicate address detected" msgstr "Adresse en double détectée" @@ -1367,7 +1362,7 @@ msgstr "Route hôte en double '%s'" #, python-format msgid "Duplicate items in the list: '%s'" -msgstr "Elément en double dans la liste : '%s'" +msgstr "Eléments en double dans la liste : '%s'" #, python-format msgid "Duplicate nameserver '%s'" @@ -1386,23 +1381,23 @@ msgid "" msgstr "" "ERREUR : Impossible de trouver le fichier de configuration via les chemins " "de recherche par défaut (~/.neutron/, ~/, /etc/neutron/, /etc/) et l'option " -"'--config-file' !" +"'--config-file' ." msgid "" "Either one of parameter network_id or router_id must be passed to _get_ports " "method." msgstr "" -"Le paramètre network_id ou le paramètre router_id doit être passé à la " +"Le paramètre network_id ou le paramètre router_id doit être transmis à la " "méthode _get_ports." msgid "Either subnet_id or port_id must be specified" msgstr "L'ID sous-réseau ou l'ID port doit être spécifié." msgid "Empty physical network name." -msgstr "Nom du Réseau Physique vide." +msgstr "Nom du réseau physique vide." msgid "Empty subnet pool prefix list." -msgstr "Liste de préfixes de pool de sous-réseau vide." +msgstr "Liste de préfixes de pool de sous-réseaux vide." msgid "Enable FWaaS" msgstr "Activer FWaaS" @@ -1411,7 +1406,7 @@ msgid "Enable HA mode for virtual routers." msgstr "Activer le mode haute disponibilité pour les routeurs virtuels." msgid "Enable SSL on the API server" -msgstr "Active SSL sur le serveur API" +msgstr "Activer SSL sur le serveur d'API" msgid "" "Enable VXLAN on the agent. Can be enabled when agent is managed by ml2 " @@ -1429,7 +1424,7 @@ msgstr "" "Activez le canal répondeur ARP local s'il est pris en charge. Requiert le " "pilote l2population OVS 2.1 et ML2. Permet au commutateur (lors de la prise " "en charge d'une superposition) de répondre à une demande ARP locale sans " -"effectuer de diffusion ARP coûteuse dans le réseau Overlay." +"effectuer de diffusion ARP coûteuse sur le réseau Overlay." msgid "" "Enable local ARP responder which provides local responses instead of " @@ -1449,8 +1444,8 @@ msgid "" "is available if this option is True." msgstr "" "Activer les services sur un agent ayant admin_state_up avec une valeur " -"False. Si cette option est False, lorsque admin_state_up d'un agent se voit " -"attribuer la valeur False, les services qui y sont associés seront " +"False. Si cette option est False, lorsque admin_state_up pour un agent se " +"voit attribuer la valeur False, les services qui y sont associés seront " "automatiquement désactivés. Les agents ayant admin_state_up avec la valeur " "False ne sont pas sélectionnés pour la planification automatique, quelle que " "soit la valeur de cette option. Toutefois, il est possible de procéder à une " @@ -1471,13 +1466,13 @@ msgstr "" "adresse IP appartenant au port dont elles proviennent. Remarque : Cela " "permet d'éviter l'usurpation des machines virtuelles connectées à cet agent, " "cela ne les protège pas d'autres unités capables d'usurpation (par exemple, " -"des unités virtualisées ou des machines virtuelles connectées à des agents " -"sans cet indicateur défini sur True). Aucune règle d'usurpation ne sera " -"ajoutée aux ports dont la sécurité est désactivée. Pour LinuxBridge, " -"ebtables est requis. Pour OVS, il est nécessaire de disposer d'une version " -"prenant en charge les en-têtes ARP correspondants. Cette option va être " -"retirée dans Newton, l'unique façon de désactiver la protection sera donc " -"via l'extension de port de sécurité." +"unités bare metal ou machines virtuelles connectées à des agents sans cet " +"indicateur défini sur True). Aucune règle d'usurpation ne sera ajoutée aux " +"ports dont la sécurité est désactivée. Pour LinuxBridge, ebtables est " +"requis. Pour OVS, il est nécessaire de disposer d'une version prenant en " +"charge les en-têtes ARP correspondants. Cette option va être retirée dans " +"Newton, l'unique façon de désactiver la protection sera donc via l'extension " +"de sécurité de port." msgid "" "Enable/Disable log watch by metadata proxy. It should be disabled when " @@ -1487,13 +1482,13 @@ msgid "" "metadata_proxy_user: watch log is enabled if metadata_proxy_user is agent " "effective user id/name." msgstr "" -"Activer/Désactiver la surveillance de journaux par proxy de métadonnées. " -"Elle doit être désactivée lorsque metadata_proxy_user/group n'est pas " -"autorisé à lire/écrire son fichier journal et l'option copytruncate " -"logrotate doit être utilisée si logrotate est activée sur les fichiers " -"journaux de proxy de métadonnées. La valeur par défaut de l'option est " -"déduite de metadata_proxy_user : la surveillance des journaux est activée si " -"metadata_proxy_user correspondà l'ID/au nom de l'utilisateur effectif de " +"Activer/Désactiver la surveillance des journaux par le proxy de métadonnées. " +"Doit être désactivée lorsque metadata_proxy_user/group n'est pas autorisé à " +"lire/écrire son fichier journal et l'option copytruncate logrotate doit être " +"utilisée si logrotate est activé sur les fichiers journaux de proxy de " +"métadonnées. La valeur par défaut de l'option est déduite de " +"metadata_proxy_user : la surveillance des journaux est activée si " +"metadata_proxy_user correspond à l'ID/au nom de l'utilisateur effectif de " "l'agent." msgid "" @@ -1568,7 +1563,7 @@ msgstr "Erreur lors de la lecture de %s" msgid "" "Exceeded %s second limit waiting for address to leave the tentative state." msgstr "" -"Limite dépassée de %s secondes, en attente adresse pour sortie de l'état de " +"Limite dépassée de %s secondes, en attente d'adresse pour quitter l'état de " "tentative." msgid "Exceeded maximum amount of fixed ips per port." @@ -1583,8 +1578,8 @@ msgid "" "Exit code: %(returncode)d; Stdin: %(stdin)s; Stdout: %(stdout)s; Stderr: " "%(stderr)s" msgstr "" -"Code de sortie: %(returncode)d; Stdin: %(stdin)s; Stdout: %(stdout)s; " -"Stderr: %(stderr)s" +"Code de sortie : %(returncode)d; Stdin : %(stdin)s; Stdout : %(stdout)s; " +"Stderr : %(stderr)s" #, python-format msgid "Extension %(driver)s failed." @@ -1595,7 +1590,7 @@ msgid "" "Extension driver %(driver)s required for service plugin %(service_plugin)s " "not found." msgstr "" -"Le pilote d'extension %(driver)s requis pour le plugin de service " +"Le pilote d'extension %(driver)s requis pour le plug-in de service " "%(service_plugin)s est introuvable." msgid "" @@ -1614,7 +1609,7 @@ msgstr "Liste d'extensions à utiliser." #, python-format msgid "Extensions not found: %(extensions)s." -msgstr "Extensions non trouvé: %(extensions)s " +msgstr "Extensions introuvable : %(extensions)s " #, python-format msgid "External DNS driver %(driver)s could not be found." @@ -1632,7 +1627,7 @@ msgid "" msgstr "" "Le réseau externe %(external_network_id)s n'est pas accessible à partir du " "sous-réseau %(subnet_id)s. Par conséquent, il est impossible d'associer le " -"port %(port_id)s avec une adresse IP flottante." +"port %(port_id)s à une adresse IP flottante." #, python-format msgid "" @@ -1656,8 +1651,8 @@ msgstr "" #, python-format msgid "Failed rescheduling router %(router_id)s: no eligible l3 agent found." msgstr "" -"Echec de la replanification du routeur %(router_id)s : aucun agent l3 " -"éligible trouvé." +"Echec de replanification du routeur %(router_id)s : aucun agent l3 éligible " +"trouvé." #, python-format msgid "Failed scheduling router %(router_id)s to the L3 Agent %(agent_id)s." @@ -1669,59 +1664,58 @@ msgid "" "Failed to allocate a VRID in the network %(network_id)s for the router " "%(router_id)s after %(max_tries)s tries." msgstr "" -"Echec de l'allocation d'un identificateur de routeur virtuel dans le réseau " +"Echec d'allocation d'un identificateur de routeur virtuel sur le réseau " "%(network_id)s pour le routeur %(router_id)s après %(max_tries)s tentatives." #, python-format msgid "Failed to allocate subnet: %(reason)s." -msgstr "Échec d'allocation de sous-réseau : %(reason)s." +msgstr "Echec d'allocation de sous-réseau : %(reason)s." msgid "" "Failed to associate address scope: subnetpools within an address scope must " "have unique prefixes." msgstr "" -"Échec de l'association de la portée d'adresse : les pools de sous-réseau au " +"Echec d'association de la portée d'adresse : les pools de sous-réseau au " "sein d'une portée d'adresse doivent avoir des préfixes uniques." #, python-format msgid "Failed to check policy %(policy)s because %(reason)s." -msgstr "Échec pour vérifier la politique %(policy)s car %(reason)s." +msgstr "Echec de vérification de la stratégie %(policy)s car %(reason)s." #, python-format msgid "" "Failed to create a duplicate %(object_type)s: for attribute(s) " "%(attributes)s with value(s) %(values)s" msgstr "" -"Echec de la création d'un élément %(object_type)s en double pour le ou les " -"attribut(s) %(attributes)s avec la ou les valeur(s) %(values)s" +"Echec de création d'un élément %(object_type)s en double pour le ou les " +"attributs %(attributes)s avec la ou les valeurs %(values)s" #, python-format msgid "" "Failed to create port on network %(network_id)s, because fixed_ips included " "invalid subnet %(subnet_id)s" msgstr "" -"Echec de la création de port sur le réseau %(network_id)s car les adresses " -"IP fixes incluent le sous-réseau non valide %(subnet_id)s " +"Echec de création de port sur le réseau %(network_id)s car les adresses IP " +"fixes incluent un sous-réseau non valide %(subnet_id)s " #, python-format msgid "Failed to init policy %(policy)s because %(reason)s." -msgstr "Échec d'initialisation de la stratégie %(policy)s car %(reason)s." +msgstr "Echec d'initialisation de la stratégie %(policy)s car %(reason)s." #, python-format msgid "Failed to locate source for %s." -msgstr "Échec pour localiser la source de %s." +msgstr "Echec de localisation de la source de %s." #, python-format msgid "Failed to parse request. Parameter '%s' not specified" -msgstr "Echec de l'analyse de la demande. Paramètre '%s' non spécifié" +msgstr "Echec d'analyse de la demande. Paramètre '%s' non spécifié" #, python-format msgid "Failed to parse request. Required attribute '%s' not specified" -msgstr "" -"Echec de l'analyse de la demande. Attribut obligatoire '%s' non spécifié" +msgstr "Echec d'analyse de la demande. Attribut obligatoire '%s' non spécifié" msgid "Failed to remove supplemental groups" -msgstr "Echec de la suppression des groupes supplémentaires" +msgstr "Echec de suppression des groupes supplémentaires" #, python-format msgid "Failed to set gid %s" @@ -1733,10 +1727,10 @@ msgstr "Echec de la définition de l'UID %s" #, python-format msgid "Failed to set-up %(type)s tunnel port to %(ip)s" -msgstr "Echec de la configuration du port de tunnel %(type)s sur %(ip)s" +msgstr "Echec de configuration du port de tunnel %(type)s sur %(ip)s" msgid "Failure applying iptables rules" -msgstr "Échec lors de la mise à jour des règles iptables" +msgstr "Echec lors de la mise à jour des règles iptables" #, python-format msgid "Failure waiting for address %(address)s to become ready: %(reason)s" @@ -1769,10 +1763,11 @@ msgid "" "%s(internal_ip)s and therefore cannot be bound." msgstr "" "L'adresse IP flottante %(floatingip_id)s est associée à l'adresse non IPV4 " -"%s(internal_ip)s, par conséquent, elle ne peut pas être liée. " +"%s(internal_ip)s, et par conséquent, elle ne peut pas être liée. " msgid "For TCP/UDP protocols, port_range_min must be <= port_range_max" -msgstr "Pour les protocole TCP/UDP, port_range_min doit être <= port_range_max" +msgstr "" +"Pour les protocoles TCP/UDP, port_range_min doit être <= port_range_max" #, python-format msgid "For class %(object_type)s missing primary keys: %(missing_keys)s" @@ -1781,7 +1776,7 @@ msgstr "" "%(missing_keys)s" msgid "Force ip_lib calls to use the root helper" -msgstr "Forcez les appels ip_lib à utiliser Root Helper" +msgstr "Forcer les appels ip_lib à utiliser Root Helper" #, python-format msgid "Found duplicate extension: %(alias)s." @@ -1792,7 +1787,7 @@ msgid "" "Found overlapping allocation pools: %(pool_1)s %(pool_2)s for subnet " "%(subnet_cidr)s." msgstr "" -"Chevauchement de pools d'allocation trouvé :%(pool_1)s %(pool_2)s pour le " +"Chevauchement de pools d'allocation trouvé : %(pool_1)s %(pool_2)s pour le " "sous-réseau %(subnet_cidr)s." msgid "Gateway IP version inconsistent with allocation pool version" @@ -1826,8 +1821,8 @@ msgstr "" "La taille de l'en-tête d'encapsulation Geneve est dynamique. Cette valeur " "est utilisée pour calculer la valeur MTU maximum du pilote. Il s'agit de la " "somme des tailles des en-têtes ETH + IP + UDP + GENEVE externes. La taille " -"par défaut pour ce champ est de 50, taille de l'en-tête Geneve sans aucun en-" -"tête d'option supplémentaire." +"par défaut pour cette zone est de 50, taille de l'en-tête Geneve sans aucun " +"en-tête d'option supplémentaire." msgid "Group (gid or name) running metadata proxy after its initialization" msgstr "" @@ -1861,8 +1856,8 @@ msgstr "" msgid "How many times Neutron will retry MAC generation" msgstr "" -"Nombre de nouvelles tentatives de génération MAC ultérieurement effectuées " -"par Neutron" +"Nombre de nouvelles tentatives de génération MAC qui seront effectuées par " +"Neutron" #, python-format msgid "" @@ -1889,7 +1884,7 @@ msgstr "Identifiant du routeur" #, python-format msgid "IP address %(ip)s already allocated in subnet %(subnet_id)s" -msgstr "L'adresse IP %(ip)s est déjà dans le sous-réseaux %(subnet_id)s" +msgstr "L'adresse IP %(ip)s est déjà allouée sur le sous-réseau %(subnet_id)s" #, python-format msgid "IP address %(ip)s does not belong to subnet %(subnet_id)s" @@ -1907,7 +1902,7 @@ msgid "IP address used by Nova metadata server." msgstr "Adresse IP utilisée par le serveur de métadonnées Nova" msgid "IP allocation failed. Try again later." -msgstr "Échec de l'allocation IP. Réessayez ultérieurement." +msgstr "Echec d'allocation d'IP. Réessayez ultérieurement." msgid "IP allocation requires subnet_id or ip_address" msgstr "L'allocation d'adresse IP requiert subnet_id ou ip_address" @@ -1917,7 +1912,7 @@ msgid "" "IPTablesManager.apply failed to apply the following set of iptables rules:\n" "%s" msgstr "" -"IPTablesManager.apply n'a pas pu appliquer l'ensemble d'iptables suivant " +"IPTablesManager.apply n'a pas pu appliquer l'ensemble suivant de règles " "iptables :\n" "%s" @@ -1950,7 +1945,7 @@ msgid "" "%(subnet_id)s as the subnet is configured for automatic addresses" msgstr "" "L'adresse IPv6 %(ip)s ne peut pas être directement affectée à un port du " -"sous-réseau%(subnet_id)s car celui-ci est configuré pour l'obtention " +"sous-réseau %(subnet_id)s car celui-ci est configuré pour l'obtention " "automatique d'adresses " #, python-format @@ -1966,15 +1961,15 @@ msgid "" "advertised to running instances via DHCP and RA MTU options." msgstr "" "Si ce paramètre est défini sur True, publiez les valeurs MTU réseau si le " -"plugin principal les calcule. MTU est publié pour l'exécution d'instances " +"plug-in principal les calcule. MTU est publié pour l'exécution d'instances " "via les options DHCP et RA MTU." msgid "" "If True, then allow plugins that support it to create VLAN transparent " "networks." msgstr "" -"Si True, autorisez les plug-in qui les prennent en charge pour créer les " -"réseaux VLAN transparents." +"Si True, autorisez les plug-in qui le prennent en charge à créer des réseaux " +"VLAN transparents." msgid "" "If non-empty, the l3 agent can only configure a router that has the matching " @@ -1984,7 +1979,7 @@ msgstr "" "comporte l'ID routeur correspondant." msgid "Illegal IP version number" -msgstr "Numéro de version IP illégal" +msgstr "Numéro de version IP non conforme" #, python-format msgid "" @@ -2000,9 +1995,9 @@ msgid "" "associate with address scope %(address_scope_id)s because subnetpool " "ip_version is not %(ip_version)s." msgstr "" -"Association de pool de sous-réseau non conforme : le pool de sous-réseau " +"Association de pool de sous-réseaux non conforme : le pool de sous-réseaux " "%(subnetpool_id)s ne peut pas s'associer à la portée d'adresse " -"%(address_scope_id)s car ip_version du pool de sous-réseau n'est pas " +"%(address_scope_id)s car ip_version du pool de sous-réseaux n'est pas " "%(ip_version)s." #, python-format @@ -2010,13 +2005,13 @@ msgid "" "Illegal subnetpool association: subnetpool %(subnetpool_id)s cannot be " "associated with address scope %(address_scope_id)s." msgstr "" -"Association de pool de sous-réseau non conforme : le sous-réseau " +"Association de pool de sous-réseaux non conforme : le pool de sous-réseaux " "%(subnetpool_id)s ne peut pas être associé à la portée d'adresse " "%(address_scope_id)s." #, python-format msgid "Illegal subnetpool update : %(reason)s." -msgstr "Mise à jour de pool de sous-réseau non conforme : %(reason)s." +msgstr "Mise à jour de pool de sous-réseaux non conforme : %(reason)s." #, python-format msgid "Illegal update to prefixes: %(msg)s." @@ -2032,14 +2027,14 @@ msgstr "" "Dans certains cas, le routeur Neutron n'est pas présent pour fournir l'IP de " "métadonnées mais le serveur DHCP peut être utilisé pour fournir ces " "informations. Lorsque cette valeur est définie, cela force le serveur DHCP à " -"ajouter des routes hôtes spécifiques à la demande DHCP. Lorsque cette option " +"ajouter des routes hôte spécifiques à la demande DHCP. Lorsque cette option " "est définie, le service de métadonnées est activé pour tous les réseaux." #, python-format msgid "Incorrect pci_vendor_info: \"%s\", should be pair vendor_id:product_id" msgstr "" -"Infos pci_vendor_info incorrectes : \"%s\". Elles devraient être vendor_id:" -"product_id" +"Infos pci_vendor_info incorrectes : \"%s\". Devraient figurer sous forme de " +"paire vendor_id:product_id" msgid "" "Indicates that this L3 agent should also handle routers that do not have an " @@ -2075,7 +2070,7 @@ msgid "" msgstr "" "Pont d'intégration à utiliser. Ne modifiez pas ce paramètre à moins d'avoir " "une bonne raison pour cela. Il s'agit du nom du pont d'intégration OVS. Il y " -"en a un par hyperviseur. Le pont d'intégration fait office de 'baie " +"en existe un par hyperviseur. Le pont d'intégration fait office de 'baie " "corrective' virtuelle. Tous les VIF de machine virtuelle sont connectés à ce " "pont puis 'corrigés' d'après leur connectivité réseau." @@ -2108,7 +2103,7 @@ msgstr "" #, python-format msgid "Invalid Device %(dev_name)s: %(reason)s" -msgstr "Périphérique non valide %(dev_name)s : %(reason)s" +msgstr "Unité non valide %(dev_name)s : %(reason)s" #, python-format msgid "" @@ -2128,7 +2123,7 @@ msgstr "" #, python-format msgid "Invalid content type %(content_type)s." -msgstr "Le type de contenu %(content_type)s est invalide." +msgstr "Le type de contenu %(content_type)s n'est pas valide." #, python-format msgid "Invalid data format for IP pool: '%s'" @@ -2168,7 +2163,7 @@ msgstr "Format non valide : %s" #, python-format msgid "Invalid input for %(attr)s. Reason: %(reason)s." -msgstr "Entrée non valide pour %(attr)s. Cause : %(reason)s." +msgstr "Entrée non valide pour %(attr)s. Raison : %(reason)s." #, python-format msgid "" @@ -2194,11 +2189,11 @@ msgstr "Plage VLAN de réseau non valide : '%(vlan_range)s' - '%(error)s'." #, python-format msgid "Invalid network VXLAN port range: '%(vxlan_range)s'." -msgstr "Réseau non valide pour le range port VXLAN: '%(vxlan_range)s'." +msgstr "Réseau non valide pour la plage de ports VXLAN : '%(vxlan_range)s'." #, python-format msgid "Invalid pci slot %(pci_slot)s" -msgstr "Port pci invalide %(pci_slot)s" +msgstr "Port pci non valide %(pci_slot)s" #, python-format msgid "Invalid provider format. Last part should be 'default' or empty: %s" @@ -2208,11 +2203,11 @@ msgstr "" #, python-format msgid "Invalid resource type %(resource_type)s" -msgstr "Ressource type %(resource_type)s non valide" +msgstr "Type de ressource %(resource_type)s non valide" #, python-format msgid "Invalid route: %s" -msgstr "Chemin non valide : %s" +msgstr "Route non valide : %s" msgid "Invalid service provider format" msgstr "Format de fournisseur de service non valide" @@ -2245,7 +2240,7 @@ msgid "" "masked with 0xffff so that only the lower 16 bits will be used." msgstr "" "Marque Mangle Iptables utilisée pour marquer les demandes valides de " -"métadonnées. Cette marque sera masquée avec 0xffff de sorte que seuls les 16 " +"métadonnées. Cette marque sera masquée avec 0xffff afin que seuls les 16 " "bits les plus bas soient utilisés. " msgid "" @@ -2253,7 +2248,7 @@ msgid "" "do not leverage the neutron database should set this flag to False" msgstr "" "Assurer le suivi de l'utilisation en cours du quota de ressources dans la " -"base de données. Les plug-ins qui n'optimisent pas la base de données de " +"base de données. Les plug-ins qui n'optimisent pas la base de données " "neutron doivent affecter la valeur False à cet indicateur. " msgid "Keepalived didn't respawn" @@ -2297,14 +2292,14 @@ msgid "" msgstr "" "Liste de :: ou " "indiquant des noms physical_network utilisables pour les réseaux de " -"fournisseurs VLAN et de locataires, ainsi que les plages d'étiquettes VLAN " +"fournisseurs VLAN et de locataires, ainsi que les plages de libellés VLAN " "disponibles dans le cadre de l'allocation aux réseaux locataires." msgid "" "List of network type driver entrypoints to be loaded from the neutron.ml2." "type_drivers namespace." msgstr "" -"Liste des points d'entrées du pilote de type de réseau à charger à partir de " +"Liste des points d'entrée du pilote de type de réseau à charger à partir de " "l'espace de nom neutron.ml2.type_drivers." msgid "" @@ -2312,13 +2307,14 @@ msgid "" "default '*' to allow flat networks with arbitrary physical_network names. " "Use an empty list to disable flat networks." msgstr "" -"Liste de noms de réseau physique qui peuvent être utilisés pour créer des " -"réseaux centralisés. Utilisez par défaut '*' pour autoriser les réseaux " -"centralisés avec des noms de réseau physique arbitraires. Utilisez une " -"liste vide pour désactiver les réseaux centralisés." +"Liste de noms de réseau physique (physical_network) qui peuvent être " +"utilisés pour créer des réseaux centralisés. Utilisez par défaut '*' pour " +"autoriser les réseaux centralisés avec des noms de réseau physique " +"arbitraires. Utilisez une liste vide pour désactiver les réseaux " +"centralisés." msgid "Local IP address of the VXLAN endpoints." -msgstr "Adresse IP locale des points de terminaison VXLAN." +msgstr "Adresse IP locale des noeuds finaux VXLAN." msgid "Local IP address of tunnel endpoint." msgstr "Adresse IP locale de noeud final de tunnel." @@ -2342,7 +2338,7 @@ msgid "Location to store IPv6 RA config files" msgstr "Emplacement de stockage des fichiers de configuration IPv6 RA" msgid "Location to store child pid files" -msgstr "Emplacement de stockage des fichiers de PID enfant" +msgstr "Emplacement de stockage des fichiers PID enfant" msgid "Location to store keepalived/conntrackd config files" msgstr "" @@ -2375,15 +2371,15 @@ msgid "" "the system-wide segment_mtu setting which the agents will take into account " "when wiring VIFs." msgstr "" -"Paramètre MTU pour l'unité. Cette option va être retirée dans Newton. " -"Utilisez le paramètre segment_mtu de niveau système qui sera pris en compte " -"par les agents lors de la connexion des VIF." +"Paramètre MTU pour l'unité. Cette option sera retirée dans Newton. Utilisez " +"le paramètre segment_mtu de niveau système qui sera pris en compte par les " +"agents lors de la connexion des VIF." msgid "MTU size of veth interfaces" -msgstr "Taille de MTU des interfaces veth" +msgstr "Taille MTU des interfaces veth" msgid "Make the l2 agent run in DVR mode." -msgstr "Exécuter l'agent l2 dans le mode DVR." +msgstr "Exécuter l'agent l2 en mode DVR." msgid "Malformed request body" msgstr "Format de corps de demande incorrect" @@ -2434,14 +2430,14 @@ msgid "" msgstr "" "Taille maximum d'un paquet IP (MTU) qui peut traverser l'infrastructure de " "réseau physique sous-jacente sans fragmentation. Pour les instances " -"utilisant un réseau en libre service/privé, Neutron soustrait la valeur de " -"surcharge du protocole de superposition de cette valeur et la fournit aux " -"instances via DHCP option 26. Par exemple, si la valeur 9000 est utilisée, " -"DHCP fournit la valeur 8950 aux instances utilisant un réseau VXLAN qui " -"contient 50 octets de surcharge. La valeur 0 désactive cette fonction et les " -"instances utilisent généralement par défaut la valeur 1500 MTU. Seules les " -"instances sont impactées et non les composants réseau Neutron comme les " -"ponts et les routeurs." +"utilisant un réseau en libre-service/privé, Neutron soustrait de cette " +"valeur la valeur de surcharge du protocole de superposition et la fournit " +"aux instances via DHCP option 26. Par exemple, si la valeur 9000 est " +"utilisée, DHCP fournit la valeur 8950 aux instances utilisant un réseau " +"VXLAN qui contient 50 octets de surcharge. La valeur 0 désactive cette " +"fonction et les instances utilisent généralement par défaut la valeur 1500 " +"MTU. Seules les instances sont impactées et non les composants réseau " +"Neutron comme les ponts et les routeurs." msgid "" "Metadata Proxy UNIX domain socket mode, 4 values allowed: 'deduce': deduce " @@ -2453,12 +2449,12 @@ msgid "" msgstr "" "Mode du socket de domaine UNIX de proxy de métadonnées, 4 valeurs " "autorisées : 'deduce' : mode de déduction à partir des valeurs de " -"metadata_proxy_user/group, 'user' : mode du socket de proxy de métadonnées " -"défini sur 0o644, à utiliser lorsque metadata_proxy_user correspond à " -"l'utilisateur ou la racine effectif de l'agent, 'group' : mode du socket de " +"metadata_proxy_user/group ; 'user' : mode du socket de proxy de métadonnées " +"défini sur 0o644, à utiliser lorsque metadata_proxy_user correspond à la " +"racine ou à l'utilisateur effectif de l'agent ; 'group' : mode du socket de " "proxy de métadonnées défini sur 0o664,à utiliser lorsque " -"metadata_proxy_group correspond au groupe ou à la racine effectif de " -"l'agent, 'all' : mode du socket de proxy de métadonnées défini sur 0o666, à " +"metadata_proxy_group correspond à la racine ou au groupe effectif de " +"l'agent ; 'all' : mode du socket de proxy de métadonnées défini sur 0o666, à " "utiliser dans les autres cas." msgid "Metering driver" @@ -2466,19 +2462,19 @@ msgstr "Pilote de décompte" #, python-format msgid "Metering label %(label_id)s does not exist" -msgstr "L'étiquette de mesure %(label_id)s n'existe pas" +msgstr "Le libellé de mesure %(label_id)s n'existe pas" #, python-format msgid "Metering label rule %(rule_id)s does not exist" -msgstr "La règle d'étiquette de mesure %(rule_id)s n'existe pas" +msgstr "La règle de libellé de mesure %(rule_id)s n'existe pas" #, python-format msgid "" "Metering label rule with remote_ip_prefix %(remote_ip_prefix)s overlaps " "another" msgstr "" -"La règle d'étiquette de mesure avec remote_ip_prefix %(remote_ip_prefix)s " -"chevauche un(e) autre" +"La règle de libellé de mesure avec remote_ip_prefix %(remote_ip_prefix)s en " +"chevauche une autre" msgid "Method cannot be called within a transaction." msgstr "La méthode ne peut pas être appelée au sein d'une transaction." @@ -2494,7 +2490,7 @@ msgstr "Paramètre MinRtrAdvInterval pour radvd.conf" msgid "Minimize polling by monitoring ovsdb for interface changes." msgstr "" "Réduire au minimum l'interrogation en surveillant les changements " -"d'interface de l'ovsdb." +"d'interface ovsdb." msgid "" "Minimum number of L3 agents which a HA router will be scheduled on. If it is " @@ -2537,7 +2533,7 @@ msgstr "" "Groupe(s) de multidiffusion pour l'interface vxlan. Une plage d'adresses de " "groupe peut être spécifiée en utilisant la notation CIDR. Si une plage est " "indiquée, différents VNI peuvent utiliser différentes adresses de groupe, ce " -"qui réduit ou élimine le trafic de multidiffusion fallacieux vers les nœuds " +"qui réduit ou élimine le trafic de multidiffusion fallacieux vers les noeuds " "finaux de tunnel. Pour réserver un groupe unique pour chaque VNI possible " "(24 bits), utilisez /8, par exemple 239.0.0.0/8. Ce paramètre doit être " "identique sur tous les agents." @@ -2549,7 +2545,7 @@ msgstr "" #, python-format msgid "Multiple default providers for service %s" -msgstr "Fournisseurs multiples par défaut pour le service %s" +msgstr "Plusieurs fournisseurs par défaut pour le service %s" #, python-format msgid "Multiple plugins for service %s were configured" @@ -2557,16 +2553,16 @@ msgstr "Plusieurs plug-in pour le service %s ont été configurés." #, python-format msgid "Multiple providers specified for service %s" -msgstr "Fournisseurs multiples indiqués pour le service %s" +msgstr "Plusieurs fournisseurs spécifiés pour le service %s" msgid "Multiple tenant_ids in bulk security group rule create not allowed" msgstr "" -"L'existence de plusieurs ID titulaire n'est pas autorisée lors de la " -"création du règle de groupe de sécurité en bloc." +"L'existence de plusieurs ID locataire n'est pas autorisée lors de la " +"création de règle de groupe de sécurité en bloc." msgid "Must also specify protocol if port range is given." msgstr "" -"Un protocole doit aussi être précisé si une plage de ports est fournie." +"Un protocole doit également être spécifié si une plage de ports est fournie." msgid "Must specify one or more actions on flow addition or modification" msgstr "" @@ -2623,8 +2619,8 @@ msgid "" "upgrade." msgstr "" "La migrations doit être appliquée depuis la branche contract %(project)s. " -"Cela va impliquer l'arrêt de toutes les instances de serveur Neutron avant " -"la mise à niveau." +"Cette opération va nécessiter l'arrêt de toutes les instances de serveur " +"Neutron avant la mise à niveau." msgid "Negative delta (downgrade) not supported" msgstr "Delta négatif (rétromigration) non pris en charge" @@ -2664,7 +2660,7 @@ msgstr "Le réseau %s n'est pas un réseau externe valide." #, python-format msgid "Network %s is not an external network" -msgstr "Réseau %s n'est pas un réseau externe" +msgstr "Le réseau %s n'est pas un réseau externe" #, python-format msgid "" @@ -2692,16 +2688,16 @@ msgid "" "set (default behavior), no IPAM driver is used. In order to use the " "reference implementation of Neutron IPAM driver, use 'internal'." msgstr "" -"Pilote IPAM de Neutron. Si le paramètre ipam_driver n'est pas défini " -"(comportement par défaut), aucun pilote IPAM n'est utilisé. Pour pouvoir " -"utiliser l'implémentation de référence du pilote IPAM de Neutron, indiquez " -"'internal'." +"Pilote IPAM (gestion des adresses IP) de Neutron à utiliser. Si le paramètre " +"ipam_driver n'est pas défini (comportement par défaut), aucun pilote IPAM " +"n'est utilisé. Pour pouvoir utiliser l'implémentation de référence du pilote " +"IPAM de Neutron, indiquez 'internal'." msgid "Neutron Service Type Management" msgstr "Gestion du type de service Neutron" msgid "Neutron core_plugin not configured!" -msgstr "Neutron core_plugin n'est pas configuré ! " +msgstr "Neutron core_plugin n'est pas configuré." msgid "Neutron plugin provider module" msgstr "Module du fournisseur de plug-in Neutron" @@ -2717,19 +2713,18 @@ msgstr "Aucun réseau router:external par défaut" #, python-format msgid "No default subnetpool found for IPv%s" -msgstr "Aucun pool de sous-réseau par défaut trouvé pour IPv%s" +msgstr "Aucun pool de sous-réseaux par défaut trouvé pour IPv%s" msgid "No default subnetpools defined" -msgstr "Aucun pool de sous-réseau défini" +msgstr "Aucun pool de sous-réseaux défini" #, python-format msgid "No eligible l3 agent associated with external network %s found" -msgstr "Aucun agent l3 admissible trouvé associé au réseau %s" +msgstr "Aucun agent l3 admissible associé au réseau %s n'a été trouvé" #, python-format msgid "No more IP addresses available for subnet %(subnet_id)s." -msgstr "" -"Pas d'autres adresses IP disponibles pour le sous-réseau %(subnet_id)s." +msgstr "Plus d'adresses IP disponibles pour le sous-réseau %(subnet_id)s." #, python-format msgid "" @@ -2738,18 +2733,18 @@ msgid "" msgstr "" "Plus d'identificateur de routeur virtuel disponible lors de la création du " "routeur %(router_id)s. Le nombre maximum de routeurs haute disponibilité par " -"locataire est 254." +"locataire est de 254." msgid "No offline migrations pending." msgstr "Aucune migration hors ligne en attente." #, python-format msgid "No providers specified for '%s' service, exiting" -msgstr "Aucun fournisseur indiqué pour le service de '%s', sortie" +msgstr "Aucun fournisseur indiqué pour le service '%s', sortie" #, python-format msgid "No shared key in %s fields" -msgstr "Aucune clé partagée dans les champs %s" +msgstr "Aucune clé partagée dans les zones %s" msgid "No versions callback provided in ResourceVersionsManager" msgstr "Aucun rappel de versions fourni dans ResourceVersionsManager" @@ -2775,21 +2770,22 @@ msgid "" "greater than 1, the scheduler automatically assigns multiple DHCP agents for " "a given tenant network, providing high availability for DHCP service." msgstr "" -"Nombre d'agents DHCP planifiés pour héberger un réseau titulaire. Si ce " +"Nombre d'agents DHCP planifiés pour héberger un réseau locataire. Si ce " "nombre est supérieur à 1, le planificateur affecte automatiquement plusieurs " -"agents DHCP pour un réseau titulaire donné, ce qui fournit de la haute " +"agents DHCP pour un réseau locataire donné, ce qui fournit de la haute " "disponibilité au service DHCP. " msgid "Number of RPC worker processes dedicated to state reports queue" msgstr "" -"Nombre de processus worker RPC dédiés à la file d'attente des rapports d'état" +"Nombre de processus d'agent RPC dédiés à la file d'attente des rapports " +"d'état" msgid "Number of RPC worker processes for service" -msgstr "Nombre de processus RPC pour le service" +msgstr "Nombre de processus d'agent RPC pour le service" msgid "Number of backlog requests to configure the metadata server socket with" msgstr "" -"Nombre de demandes en attente avec lequel configurer le socket du serveur de " +"Nombre de demandes en attente de configuration avec le socket du serveur de " "métadonnées" msgid "Number of backlog requests to configure the socket with" @@ -2823,13 +2819,13 @@ msgstr "" msgid "" "Number of networks allowed per tenant. A negative value means unlimited." msgstr "" -"Nombre de réseaux autorisés par le locataire. Une valeur négative signifie " -"illimité" +"Nombre de réseaux autorisés par locataire. Une valeur négative signifie " +"illimité." msgid "Number of ports allowed per tenant. A negative value means unlimited." msgstr "" -"Nombre de ports autorisés par le locataire. Une valeur négative signifie " -"illimité" +"Nombre de ports autorisés par locataire. Une valeur négative signifie " +"illimité." msgid "Number of routers allowed per tenant. A negative value means unlimited." msgstr "" @@ -2844,7 +2840,7 @@ msgstr "" "événements à envoyer." msgid "Number of seconds to keep retrying to listen" -msgstr "Nombre de secondes a attendre avant d'essayer d'écouter à nouveau" +msgstr "Nombre de secondes à attendre avant d'essayer d'écouter à nouveau" msgid "" "Number of security groups allowed per tenant. A negative value means " @@ -2864,21 +2860,21 @@ msgid "" "Number of separate API worker processes for service. If not specified, the " "default is equal to the number of CPUs available for best performance." msgstr "" -"Nombre de processus de traitement d'API séparés pour le service. Si ce " -"nombre n'est pas spécifié, la valeur par défaut est égale au nombre d'UC " +"Nombre de processus d'agent d'API distincts pour le service. Si ce nombre " +"n'est pas spécifié, la valeur par défaut est égale au nombre d'UC " "disponibles pour optimiser les performances. " msgid "" "Number of separate worker processes for metadata server (defaults to half of " "the number of CPUs)" msgstr "" -"Nombre de processus de traitement séparés pour le serveur de métadonnées " +"Nombre de processus de traitement distincts pour le serveur de métadonnées " "(par défaut, la moitié du nombre d'unités centrales)" msgid "Number of subnets allowed per tenant, A negative value means unlimited." msgstr "" -"Nombre de sous-réseaux autorisés par le locataire. Une valeur négative " -"signifie illimité" +"Nombre de sous-réseaux autorisés par locataire. Une valeur négative signifie " +"illimité." msgid "" "Number of threads to use during sync process. Should not exceed connection " @@ -2895,7 +2891,7 @@ msgid "" "OVS datapath to use. 'system' is the default value and corresponds to the " "kernel datapath. To enable the userspace datapath set this value to 'netdev'." msgstr "" -"Chemin de données OVS à utiliser. 'system' est la valeur par défaut et elle " +"Chemin de données OVS à utiliser. 'system' est la valeur par défaut qui " "correspond au chemin de données du noyau. Pour activer le chemin de données " "de l'espace utilisateur, définissez cette valeur sur 'netdev'." @@ -2904,11 +2900,11 @@ msgstr "Répertoire de socket OVS vhost-user." #, python-format msgid "OVSDB Error: %s" -msgstr "Erreur OVSDB: %s " +msgstr "Erreur OVSDB : %s " #, python-format msgid "Object action %(action)s failed because: %(reason)s." -msgstr "L'action de l'objet %(action)s a échoué car : %(reason)s" +msgstr "Echec de l'action de l'objet %(action)s car : %(reason)s" msgid "Only admin can view or configure quota" msgstr "Seul l'administrateur peut afficher ou configurer des quotas" @@ -2929,8 +2925,8 @@ msgstr "" msgid "Only allowed to update rules for one security profile at a time" msgstr "" -"Les règles peuvent être mises à jour pour un seul profil de sécurité à la " -"fois." +"Les règles peuvent uniquement être mises à jour pour un profil de sécurité à " +"la fois." msgid "Only remote_ip_prefix or remote_group_id may be provided." msgstr "Seul remote_ip_prefix ou remote_group_id peut être fourni." @@ -2948,14 +2944,14 @@ msgstr "" #, python-format msgid "Operation not supported on device %(dev_name)s" -msgstr "Opération non prise en charge sur le périphérique %(dev_name)s" +msgstr "Opération non prise en charge sur l'unité %(dev_name)s" msgid "" "Ordered list of network_types to allocate as tenant networks. The default " "value 'local' is useful for single-box testing but provides no connectivity " "between hosts." msgstr "" -"Liste triée des éléments network_types à allouer en tant que réseaux " +"Liste ordonnée des éléments network_types à allouer en tant que réseaux " "locataires. La valeur par défaut 'local' est utile pour les tests single-box " "mais elle ne fournit aucune connectivité entre les hôtes." @@ -2966,7 +2962,7 @@ msgid "Owner type of the device: network/compute" msgstr "Type de propriétaire de l'unité : réseau/ordinateur" msgid "POST requests are not supported on this resource." -msgstr "Les requêtes POST ne sont pas prises en charge sur cette ressource." +msgstr "Les demandes POST ne sont pas prises en charge sur cette ressource." #, python-format msgid "Package %s not installed" @@ -2978,7 +2974,7 @@ msgstr "Le paramètre %(param)s doit être de type %(param_type)s." #, python-format msgid "Parsing bridge_mappings failed: %s." -msgstr "Echec de l'analyse syntaxique bridge_mappings : %s." +msgstr "Echec de l'analyse syntaxique des bridge_mappings : %s." msgid "Parsing supported pci_vendor_devs failed" msgstr "Echec de l'analyse syntaxique des pci_vendor_devs pris en charge" @@ -3008,7 +3004,7 @@ msgstr "" "d'intégration." msgid "Per-tenant subnet pool prefix quota exceeded." -msgstr "Quota de préfixes de pool de sous réseau par locataire dépassé." +msgstr "Quota de préfixes de pool de sous-réseaux par locataire dépassé." msgid "Phase upgrade options do not accept revision specification" msgstr "" @@ -3016,11 +3012,11 @@ msgstr "" "révision" msgid "Ping timeout" -msgstr "Délai d'expiration de la commande ping" +msgstr "Délai d'attente de la commande ping" #, python-format msgid "Plugin '%s' not found." -msgstr "Le plugin '%s' n'est pas trouvé." +msgstr "Le plugin '%s' est introuvable." msgid "Plugin does not support updating provider attributes" msgstr "" @@ -3035,7 +3031,7 @@ msgstr "Le port %(id)s ne dispose pas de l'adresse IP fixe %(address)s." #, python-format msgid "Port %(port)s does not exist on %(bridge)s!" -msgstr "Le port %(port)s au sein du pont %(bridge)s" +msgstr "Le port %(port)s au sein du pont %(bridge)s n'existe pas" #, python-format msgid "Port %(port_id)s is already acquired by another DHCP agent" @@ -3046,7 +3042,7 @@ msgid "" "Port %(port_id)s is associated with a different tenant than Floating IP " "%(floatingip_id)s and therefore cannot be bound." msgstr "" -"Le port %(port_id)s est associé à un titulaire différent de celui de " +"Le port %(port_id)s est associé à un locataire différent de celui de " "l'adresse IP flottante %(floatingip_id)s et ne peut donc pas être lié. " #, python-format @@ -3055,7 +3051,7 @@ msgstr "Le port %(port_id)s n'est pas géré par cet agent. " #, python-format msgid "Port %s does not exist" -msgstr "Le port %s est inexistant." +msgstr "Le port %s n'existe pas" #, python-format msgid "" @@ -3070,7 +3066,7 @@ msgid "" "Port Security must be enabled in order to have allowed address pairs on a " "port." msgstr "" -"La sécurité du port doit être activée pour avoir les paires d'adresse " +"La sécurité du port doit être activée pour avoir les paires d'adresses " "autorisées sur un port." msgid "" @@ -3078,14 +3074,15 @@ msgid "" "address until security group is removed" msgstr "" "Un groupe de sécurité est associé au port. Impossible de désactiver la " -"sécurité ou l'adresse IP du port tant que le groupe de sécurité est supprimé" +"sécurité ou l'adresse IP du port tant que le groupe de sécurité n'a pas été " +"retiré" msgid "" "Port security must be enabled and port must have an IP address in order to " "use security groups." msgstr "" "La sécurité du port doit être activée et le port doit avoir une adresse IP " -"pour utiliser les groupes de sécurité." +"pour utiliser des groupes de sécurité." msgid "" "Port to listen on for OpenFlow connections. Used only for 'native' driver." @@ -3129,7 +3126,7 @@ msgstr "Le nom de fournisseur %(name)s est limité à %(len)s caractères" #, python-format msgid "QoS Policy %(policy_id)s is used by %(object_type)s %(object_id)s." msgstr "" -"Stratégie QoS %(policy_id)s est utilisée par %(object_type)s %(object_id)s." +"Stratégie QoS %(policy_id)s utilisée par %(object_type)s %(object_id)s." #, python-format msgid "" @@ -3148,12 +3145,12 @@ msgstr "" #, python-format msgid "QoS policy %(policy_id)s could not be found." -msgstr "La politique de QoS %(policy_id)s est introuvable." +msgstr "La stratégie de QoS %(policy_id)s est introuvable." #, python-format msgid "QoS rule %(rule_id)s for policy %(policy_id)s could not be found." msgstr "" -"La règle QoS %(rule_id)s pour la politique %(policy_id)s est inexistante." +"La règle QoS %(rule_id)s pour la stratégie %(policy_id)s est introuvable." #, python-format msgid "RBAC policy of type %(object_type)s with ID %(id)s not found" @@ -3174,9 +3171,9 @@ msgid "" "Range of seconds to randomly delay when starting the periodic task scheduler " "to reduce stampeding. (Disable by setting to 0)" msgstr "" -"Intervalle en secondes de retard au hasard lors du démarrage du " -"planificateur de tâches périodiques de manière à réduire les encombrements " -"(définissez ce chiffre sur 0 pour désactiver cette fonction)." +"Intervalle, en secondes, de retard aléatoire lors du démarrage du " +"planificateur de tâches périodiques permettant de réduire les encombrements " +"(définissez ce chiffre sur 0 pour désactiver la fonction)." msgid "Ranges must be in the same IP version" msgstr "Les plages doivent être dans la même version IP" @@ -3190,7 +3187,7 @@ msgstr "Les plages ne doivent pas se chevaucher" #, python-format msgid "" "Received type '%(type)s' and value '%(value)s'. Expecting netaddr.EUI type." -msgstr "Type '%(type)s' et valeur '%(value)s' reçus. Type netaddr.EUI reçu." +msgstr "Type '%(type)s' et valeur '%(value)s' reçus. Type netaddr.EUI attendu." #, python-format msgid "" @@ -3236,16 +3233,16 @@ msgid "" "for the resource being balanced. Example: dhcp_load_type=networks" msgstr "" "Représentation du type de ressource dont la charge est signalée par l'agent. " -"Il peut s'agir de \"réseaux\", \"sous-réseaux\" ou \"ports\". Lorsqu'il est " -"spécifié (la valeur par défaut est réseaux), le serveur extrait la charge " -"particulière envoyée en tant que composant de son objet de configuration " -"d'agent depuis l'état de rapport d'agent, qui correspond au nombre de " -"ressources consommées, à chaque intervalle report_interval.dhcp_load_type, " -"et pouvant être utilisées en combinaison avec network_scheduler_driver = " -"neutron.scheduler.dhcp_agent_scheduler.WeightScheduler Lorsque " -"network_scheduler_driver est WeightScheduler, dhcp_load_type peut être " -"configuré pour représenter le choix pour la ressource équilibrée. Exemple : " -"dhcp_load_type=networks" +"Il peut s'agir de \"réseaux\", \"sous-réseaux\" ou \"ports\". Lorsque le " +"type est spécifié (la valeur par défaut est réseaux), le serveur extrait la " +"charge particulière envoyée en tant que composant de son objet de " +"configuration d'agent depuis l'état de rapport d'agent, qui correspond au " +"nombre de ressources consommées, à chaque intervalle report_interval." +"dhcp_load_type, et pouvant être utilisées en combinaison avec " +"network_scheduler_driver = neutron.scheduler.dhcp_agent_scheduler." +"WeightScheduler Lorsque network_scheduler_driver est WeightScheduler, " +"dhcp_load_type peut être configuré pour représenter le choix pour la " +"ressource équilibrée. Exemple : dhcp_load_type=networks" msgid "Request Failed: internal server error while processing your request." msgstr "" @@ -3257,7 +3254,7 @@ msgid "" "Request contains duplicate address pair: mac_address %(mac_address)s " "ip_address %(ip_address)s." msgstr "" -"La demande contient la paire d'adresse en double : mac_address " +"La demande contient une paire d'adresses en double : mac_address " "%(mac_address)s ip_address %(ip_address)s." #, python-format @@ -3265,8 +3262,8 @@ msgid "" "Requested subnet with cidr: %(cidr)s for network: %(network_id)s overlaps " "with another subnet" msgstr "" -"Le sous-réseau demandé avec le routage CIDR : %(cidr)s pour le réseau : " -"%(network_id)s chevauche un autre sous-réseau" +"Le sous-réseau demandé avec CIDR : %(cidr)s pour le réseau : %(network_id)s " +"chevauche un autre sous-réseau" msgid "" "Reset flow table on start. Setting this to True will cause brief traffic " @@ -3281,7 +3278,7 @@ msgstr "La ressource %(resource)s %(resource_id)s est introuvable." #, python-format msgid "Resource %(resource_id)s of type %(resource_type)s not found" -msgstr "Ressource %(resource_id)s de type %(resource_type)s non trouvée." +msgstr "Ressource %(resource_id)s de type %(resource_type)s introuvable" #, python-format msgid "" @@ -3299,10 +3296,10 @@ msgid "" "deprecated for removal." msgstr "" "Nom(s) de ressource pris en charge dans les fonctions de quota. Cette option " -"est désormaisobsolète pour retrait." +"est désormais obsolète et devrait être retirée." msgid "Resource not found." -msgstr "Ressource non trouvé." +msgstr "Ressource introuvable." msgid "Resources required" msgstr "Ressources obligatoires" @@ -3318,8 +3315,7 @@ msgstr "" "commande directement." msgid "Root helper daemon application to use when possible." -msgstr "" -"Application de démon d'assistant racine à utiliser en cas de possibilité." +msgstr "Application de démon d'assistant racine à utiliser si possible." msgid "Root permissions are required to drop privileges." msgstr "Les droits root sont obligatoires pour supprimer des privilèges." @@ -3365,8 +3361,8 @@ msgid "" "deleted, as it is required by one or more floating IPs." msgstr "" "L'interface de routeur du sous-réseau %(subnet_id)s sur le routeur " -"%(router_id)s être supprimée car elle est requise par une ou plusieurs " -"adresses IP flottantes." +"%(router_id)s ne peut pas être supprimée car elle est requise par une ou " +"plusieurs adresses IP flottantes." #, python-format msgid "" @@ -3374,8 +3370,8 @@ msgid "" "deleted, as it is required by one or more routes." msgstr "" "L'interface de routeur du sous-réseau %(subnet_id)s sur le routeur " -"%(router_id)s être supprimée car elle est requise par une ou plusieurs " -"routes." +"%(router_id)s ne peut pas être supprimée car elle est requise par une ou " +"plusieurs routes." msgid "Router port must have at least one fixed IP" msgstr "Le port de routeur doit avoir au moins une IP fixe" @@ -3388,7 +3384,7 @@ msgid "" "Row doesn't exist in the DB. Request info: Table=%(table)s. Columns=" "%(columns)s. Records=%(records)s." msgstr "" -"La ligne n'existe pas dans la base de données. Info demande : Table=" +"La ligne n'existe pas dans la base de données. Infos demande : Table=" "%(table)s. Colonnes=%(columns)s. Enregistrements=%(records)s." msgid "Run as daemon." @@ -3414,15 +3410,15 @@ msgstr "" "moitié de agent_down_time." msgid "Seconds between running periodic tasks" -msgstr "Temps en secondes entre deux tâches périodiques" +msgstr "Secondes écoulées entre l'exécution de deux tâches périodiques" msgid "" "Seconds to regard the agent is down; should be at least twice " "report_interval, to be sure the agent is down for good." msgstr "" "Nombre de secondes avant de considérer que l'agent est arrêté ; cette valeur " -"doit être au moins le double de report_interval, pour s'assurer que l'agent " -"est effectivement arrêté." +"doit être au moins le double de report_interval, afin de s'assurer que " +"l'agent est effectivement arrêté." #, python-format msgid "Security Group %(id)s %(reason)s." @@ -3459,13 +3455,12 @@ msgid "" "values %(values)s and integer representations [0 to 255] are supported." msgstr "" "Le protocole %(protocol)s de la règle du groupe de sécurité n'est pas pris " -"en charge. Seules les valeurs de protocole Les valeurs %(values)s et les " -"représentations sous forme d'entier [0 à 255] sont prises en charge." +"en charge. Seules les valeurs de protocole %(values)s et les représentations " +"sous forme d'entier [0 à 255] sont prises en charge." msgid "Segments and provider values cannot both be set." msgstr "" -"Il n'est pas possible de définir à la fois des segments et des valeurs de " -"fournisseur." +"Impossible de définir à la fois des segments et des valeurs de fournisseur." msgid "Selects the Agent Type reported" msgstr "Sélectionne le type d'agent signalé" @@ -3478,16 +3473,15 @@ msgstr "" "(fixed_ips/floatingip) pour que nova puisse mettre à jour son cache." msgid "Send notification to nova when port status changes" -msgstr "" -"Envoyer une notification à nova lors de la modification du statut de port" +msgstr "Envoyer une notification à nova lors du changement du statut de port" msgid "" "Send this many gratuitous ARPs for HA setup, if less than or equal to 0, the " "feature is disabled" msgstr "" "Envoyez ces nombreux protocoles de résolution d'adresse gratuits pour la " -"configuration haute disponibilité (HA), si la valeur est inférieure ou égale " -"à 0, la fonction est désactivée" +"configuration HA (haute disponibilité) ; si la valeur est inférieure ou " +"égale à 0, la fonction est désactivée" #, python-format msgid "Service Profile %(sp_id)s could not be found." @@ -3540,23 +3534,23 @@ msgid "" "Set new timeout in seconds for new rpc calls after agent receives SIGTERM. " "If value is set to 0, rpc timeout won't be changed" msgstr "" -"Redéfinir le délai d'attente (en secondes) des nouveaux appels RPC observé " -"une fois que l'agent a reçu SIGTERM. Si la valeur est définie sur 0, le " +"Définir un nouveau délai d'attente (en secondes) pour les nouveaux appels " +"RPC après que l'agent a reçu SIGTERM. Si la valeur est définie sur 0, le " "délai d'attente RPC reste inchangé" msgid "" "Set or un-set the don't fragment (DF) bit on outgoing IP packet carrying GRE/" "VXLAN tunnel." msgstr "" -"Définissez ou annulez la définition du bit de fragment sur le paquet IP " -"sortant véhiculant le tunnel GRE/VXLAN." +"Définissez ou annulez la définition du bit DF sur le paquet IP sortant " +"véhiculant le tunnel GRE/VXLAN." msgid "" "Set or un-set the tunnel header checksum on outgoing IP packet carrying GRE/" "VXLAN tunnel." msgstr "" "Définir ou annuler la définition du total de contrôle de l'en-tête de tunnel " -"sur un paquet IP en cours qui transporte le tunnel GRE/VXLAN. " +"sur un paquet IP sortant qui transporte le tunnel GRE/VXLAN. " msgid "Shared address scope can't be unshared" msgstr "Impossible d'annuler le partage d'une portée d'adresse partagée" @@ -3565,19 +3559,19 @@ msgid "" "Specifying 'tenant_id' other than authenticated tenant in request requires " "admin privileges" msgstr "" -"Pour indiquer un 'tenant_id' autre qu'un titulaire authentifié dans la " -"demande, vous devez disposer de droits admin " +"Pour indiquer un 'tenant_id' autre qu'un projet authentifié dans la demande, " +"vous devez disposer de droits admin " msgid "String prefix used to match IPset names." msgstr "Préfixe de chaîne utilisé pour correspondre aux noms IPset." #, python-format msgid "Sub-project %s not installed." -msgstr "Le sous projet %s n'est pas installé." +msgstr "Le sous-projet %s n'est pas installé." msgid "Subnet for router interface must have a gateway IP" msgstr "" -"Le sous-réseau de l'interface de routeur doit avoir une adresse IP " +"Le sous-réseau de l'interface de routeur doit avoir une adresse IP de " "passerelle." msgid "" @@ -3591,7 +3585,7 @@ msgid "Subnet pool %(subnetpool_id)s could not be found." msgstr "Le pool de sous-réseaux %(subnetpool_id)s est introuvable." msgid "Subnet pool has existing allocations" -msgstr "Le pool de sous-réseau dispose d'allocations existantes" +msgstr "Le pool de sous-réseaux dispose d'allocations existantes" msgid "Subnet used for the l3 HA admin network." msgstr "" @@ -3602,20 +3596,20 @@ msgid "" "pool." msgstr "" "Les sous-réseaux hébergés sur le même réseau doivent être alloués à partir " -"du même pool de sous-réseau." +"du même pool de sous-réseaux." msgid "Suffix to append to all namespace names." -msgstr "Suffixe à ajouter à tous les noms d'espace nom." +msgstr "Suffixe à ajouter à tous les noms d'espace de nom." msgid "" "System-wide flag to determine the type of router that tenants can create. " "Only admin can override." msgstr "" -"Indicateur système pour déterminer le type de router que les locataires " -"peuvent créer. Seul l'administrateur peut outrepasser cela" +"Indicateur système pour déterminer le type de routeur que les locataires " +"peuvent créer. Seul l'administrateur dispose du droit de substitution." msgid "TCP Port to listen for metadata server requests." -msgstr "Port TCP d'écoute des demandes du serveur de métadonnées" +msgstr "Port TCP d'écoute des demandes de serveur de métadonnées" msgid "TCP Port used by Neutron metadata namespace proxy." msgstr "Port TCP utilisé par le proxy d'espace de nom de métadonnées Neutron" @@ -3639,12 +3633,12 @@ msgstr "La table %s ne peut être interrogée que par UUID" #, python-format msgid "Tag %(tag)s could not be found." -msgstr "Tag %(tag)s introuvable." +msgstr "Balise %(tag)s introuvable." #, python-format msgid "Tenant %(tenant_id)s not allowed to create %(resource)s on this network" msgstr "" -"Titulaire %(tenant_id)s non autorisé à créer %(resource)s sur ce réseau" +"Locataire %(tenant_id)s non autorisé à créer %(resource)s sur ce réseau" msgid "Tenant id for connecting to designate in admin context" msgstr "" @@ -3655,17 +3649,17 @@ msgstr "" "Nom de locataire pour la connexion au réseau désigné dans un contexte admin" msgid "Tenant network creation is not enabled." -msgstr "La création de réseau titulaire n'est pas activée." +msgstr "La création de réseau locataire n'est pas activée." msgid "Tenant-id was missing from quota request." -msgstr "ID titulaire manquant dans la demande de quota." +msgstr "ID locataire manquant dans la demande de quota." msgid "" "The 'gateway_external_network_id' option must be configured for this agent " "as Neutron has more than one external network." msgstr "" -"L'option 'gateway_external_network_id' doit être configuré pour cet agent " -"car Neutron a plus d'un réseau externe." +"L'option 'gateway_external_network_id' doit être configurée pour cet agent " +"car Neutron a plusieurs réseaux externes." msgid "" "The DHCP agent will resync its state with Neutron to recover from any " @@ -3687,21 +3681,21 @@ msgstr "" "Le serveur DHCP peut contribuer à fournir un support de métadonnées sur des " "réseaux isolés. Si cette valeur est définie sur True, le serveur DHCP ajoute " "des routes hôtes spécifiques à la demande DHCP. Le service de métadonnées " -"n'est activé que lorsque le sous-réseau ne contient aucun port de routeur. " -"L'instance invitée doit être configurée pour la demande de routes hôtes via " -"DHCP (Option 121). Cette option n'a aucun effet lorsque force_metadata est " -"défini sur True." +"est activé uniquement quand le sous-réseau ne contient aucun port de " +"routeur. L'instance invitée doit être configurée pour la demande de routes " +"hôtes via DHCP (Option 121). Cette option n'a aucun effet lorsque " +"force_metadata est défini sur True." #, python-format msgid "" "The HA Network CIDR specified in the configuration file isn't valid; " "%(cidr)s." msgstr "" -"Le routage CIDR du réseau haute disponibilité indiqué dans le fichier de " +"Le CIDR du réseau haute disponibilité indiqué dans le fichier de " "configuration n'est pas valide ; %(cidr)s." msgid "The UDP port to use for VXLAN tunnels." -msgstr "Port UDP a utiliser pour les tunnels VXLAN." +msgstr "Port UDP à utiliser pour les tunnels VXLAN." #, python-format msgid "" @@ -3749,12 +3743,13 @@ msgid "" "tenant ports. A 4 octet example would be dvr_base_mac = fa:16:3f:4f:00:00. " "The default is 3 octet" msgstr "" -"Adresse MAC de base utilisée pour les instances DVR uniques par Neutron. Les " -"3 premiers octets restent inchangés. Si le 4ème octet est différent de 00, " -"il sera également utilisé. Les autres seront générés de manière aléatoire. " +"Adresse MAC de base utilisée par Neutron pour les instances DVR uniques. Les " +"3 premiers octets restent inchangés. Si le 4e octet est différent de 00, il " +"sera également utilisé. Les autres seront générés de manière aléatoire. " "L'adresse 'dvr_base_mac' *doit* être différente de l'adresse 'base_mac' pour " -"éviter de les confondre avec les adresses MAC allouées pour les ports " -"titulaires. 3 octets sont utilisés par défaut. " +"éviter de les confondre avec des adresses MAC allouées pour des ports " +"locataires. Exemple à 4 octets : dvr_base_mac = fa:16:3f:4f:00:00. 3 octets " +"sont utilisés par défaut." msgid "" "The connection string for the native OVSDB backend. Requires the native " @@ -3764,7 +3759,7 @@ msgstr "" "l'interface ovsdb_interface native." msgid "The core plugin Neutron will use" -msgstr "Le core plugin de Neutron va etre utiliser" +msgstr "Le plug-in core de Neutron utilisera" #, python-format msgid "" @@ -3814,7 +3809,7 @@ msgstr "" "correspond au routeur d'un autre locataire." msgid "The host IP to bind to" -msgstr "Protocole IP hôte à connecter" +msgstr "IP hôte pour la liaison" msgid "The interface for interacting with the OVSDB" msgstr "Interface d'interaction avec OVSDB" @@ -3823,8 +3818,8 @@ msgid "" "The maximum number of items returned in a single response, value was " "'infinite' or negative integer means no limit" msgstr "" -"Nombre maximal d'éléments renvoyés dans une seule réponse, valeur définie " -"sur 'infinite' ou sur un entier négatif qui signifie illimité" +"Nombre maximal d'éléments renvoyés dans une seule réponse ; la valeur " +"définie sur 'infinite' ou sur un entier négatif signifie illimité" #, python-format msgid "" @@ -3853,26 +3848,27 @@ msgstr "" #, python-format msgid "The number of allowed address pair exceeds the maximum %(quota)s." -msgstr "Le nombre de paires d'adreses autorisé dépasse le maximum %(quota)s." +msgstr "" +"Le nombre de paires d'adresses autorisées dépasse le maximum %(quota)s." msgid "" "The number of seconds the agent will wait between polling for local device " "changes." msgstr "" -"Temps en secondes pendant lequel l'agent attendra les interrogations sur les " +"Temps en secondes pendant lequel l'agent attend les interrogations sur les " "modifications de l'unité locale." msgid "" "The number of seconds to wait before respawning the ovsdb monitor after " "losing communication with it." msgstr "" -"Le nombre de secondes d'attente avant de régénérer le moniteur ovsdb après " -"avoir perdu la communication avec ce dernier." +"Nombre de secondes d'attente avant relance du moniteur ovsdb après une perte " +"de communication avec ce dernier." msgid "The number of sort_keys and sort_dirs must be same" msgstr "" -"Le nombre de clés de tri (sort_keys) et de répertoires de tri (sort_dirs) " -"doit être identique" +"Le nombre des clés de tri (sort_keys) et celui des répertoires de tri " +"(sort_dirs) doivent être identiques" msgid "" "The path for API extensions. Note that this can be a colon-separated list of " @@ -3882,9 +3878,9 @@ msgid "" msgstr "" "Chemin des extensions API. Notez qu'il peut s'agir d'une liste de chemins " "séparés par des virgules. Par exemple : api_extensions_path = extensions:/" -"path/to/more/exts:/even/more/exts. Le __chemin__ de neutron.extensions lui " -"est ajouté, de sorte que si vos extensions figurent dans ce chemin, vous " -"n'avez pas besoin de les indiquer ici." +"path/to/more/exts:/even/more/exts. Le chemin de neutron.extensions y est " +"ajouté, de sorte que si vos extensions figurent dans ce chemin, vous n'avez " +"pas besoin de les indiquer ici." msgid "The physical network name with which the HA network can be created." msgstr "" @@ -3896,11 +3892,11 @@ msgid "The port '%s' was deleted" msgstr "Le port '%s' a été supprimé" msgid "The port to bind to" -msgstr "Port à connecter" +msgstr "Port pour la liaison" #, python-format msgid "The requested content type %s is invalid." -msgstr "Le type de contenu %s de la requete est invalide." +msgstr "Le type de contenu demandé %s n'est pas valide." msgid "The resource could not be found." msgstr "La ressource est introuvable." @@ -3919,7 +3915,7 @@ msgstr "" "demandée." msgid "The service plugins Neutron will use" -msgstr "Plug-in de service utilisés ultérieurement par Neutron" +msgstr "Plug-in de service qui sera utilisé par Neutron" #, python-format msgid "The subnet request could not be satisfied because: %(reason)s" @@ -3928,8 +3924,8 @@ msgstr "Impossible de répondre à la demande de sous-réseau. Motif : %(reason) #, python-format msgid "The subproject to execute the command against. Can be one of: '%s'." msgstr "" -"Sous-projet sur lequel la commande doit être exécutée. Valeurs possibles : " -"'%s'." +"Sous-projet en fonction duquel la commande doit être exécutée. Valeurs " +"possibles : '%s'." msgid "The type of authentication to use" msgstr "Type d'authentification à utiliser" @@ -3948,16 +3944,15 @@ msgid "" "must be used for an L3 agent running on a centralized node (or in single-" "host deployments, e.g. devstack)" msgstr "" -"Mode de fonctionnement de l'agent. Les modes sont : 'legacy' - ceci préserve " -"le comportement existant où l'agent de niveau 3 est déployé sur un noeud " -"centralisé de mise en réseau pour fournir des services de niveau 3 comme " -"DNAT et SNAT. Utilisez ce mode si vous ne voulez pas adopter le routeur " -"virtuel distribué (DVR). 'dvr' - ce mode active la fonctionnalité DVR et " -"doit être utilisé pour un agent de niveau 3 qui s'exécute sur un hôte de " -"traitement. 'dvr_snat' - active la prise en charge SNAT centralisée " -"conjointement avec DVR. Ce mode doit être utilisé pour un agent de niveau 3 " -"fonctionnant sur un noeud centralisé (ou dans des déploiements à un seul " -"hôte, par ex. devstack)" +"Mode de fonctionnement de l'agent. Les modes autorisés sont : 'legacy' - " +"préserve le comportement existant où l'agent L3 est déployé sur un noeud " +"centralisé de mise en réseau pour fournir des services L3 comme DNAT et " +"SNAT. Utilisez ce mode si vous ne voulez pas adopter le routeur virtuel " +"distribué (DVR). 'dvr' - ce mode active la fonctionnalité DVR et doit être " +"utilisé pour un agent L3 qui s'exécute sur un hôte de calcul. 'dvr_snat' - " +"active la prise en charge SNAT centralisée conjointement avec DVR. Ce mode " +"doit être utilisé pour un agent L3 fonctionnant sur un noeud centralisé (ou " +"dans des déploiements à un seul hôte, par ex. devstack)" msgid "" "There are routers attached to this network that depend on this policy for " @@ -3974,7 +3969,7 @@ msgstr "" "de Neutron. 'pecan' est une nouvelle réécriture expérimentale du serveur API." msgid "Timeout" -msgstr "Délai d'expiration" +msgstr "Délai d'attente" msgid "" "Timeout in seconds for ovs-vsctl commands. If the timeout expires, ovs " @@ -4001,7 +3996,7 @@ msgid "" "Too long prefix provided. New name would exceed given length for an " "interface name." msgstr "" -"Le préfixe fourni est trop long. Un nouveau nom dépasserait la longueur " +"Le préfixe fourni est trop long. Le nouveau nom dépasserait la longueur " "indiquée pour un nom d'interface." msgid "Too many availability_zone_hints specified" @@ -4011,9 +4006,9 @@ msgid "" "True to delete all ports on all the OpenvSwitch bridges. False to delete " "ports created by Neutron on integration and external network bridges." msgstr "" -"La valeur est vraie pour la suppression de tous les ports sur tous les ponts " -"OpenvSwitch. Elle est fausse pour la suppression des ports créés par Neutron " -"lors de l'intégration et des ponts de réseau externes." +"La valeur est vraie (true) pour la suppression de tous les ports sur tous " +"les ponts OpenvSwitch. Elle est fausse (false) pour la suppression des ports " +"créés par Neutron sur les ponts d'intégration et de réseau externe." msgid "Tunnel IP value needed by the ML2 plugin" msgstr "Valeur IP de tunnel requise par le plug-in ML2" @@ -4082,7 +4077,7 @@ msgid "" "exceeds the limit %(quota)s." msgstr "" "Impossible de terminer l'opération pour le sous-réseau %(subnet_id)s. Le " -"nombre de routes hôtes dépasse la limite %(quota)s." +"nombre de routes hôte dépasse la limite %(quota)s." #, python-format msgid "" @@ -4090,7 +4085,7 @@ msgid "" "are one or more subnet pools in use on the address scope" msgstr "" "Impossible de terminer l'opération sur la portée d'adresse " -"%(address_scope_id)s. Un ou plusieurs pools de sous-réseau supplémentaires " +"%(address_scope_id)s. Un ou plusieurs pools de sous-réseaux supplémentaires " "sont utilisés sur la portée d'adresse" #, python-format @@ -4101,7 +4096,7 @@ msgid "Unable to create the Agent Gateway Port" msgstr "Impossible de créer le port de passerelle d'agent" msgid "Unable to create the SNAT Interface Port" -msgstr "Impossible de créer l'interface du port SNAT" +msgstr "Impossible de créer le port d'interface SNAT" #, python-format msgid "" @@ -4115,12 +4110,12 @@ msgid "" "Unable to create the network. No available network found in maximum allowed " "attempts." msgstr "" -"Impossible de créer le réseau. Aucun réseau disponible trouvé dans le " +"Impossible de créer le réseau. Aucun réseau disponible trouvé avec le " "maximum de tentatives autorisées." #, python-format msgid "Unable to delete subnet pool: %(reason)s." -msgstr "Impossible de supprimer le pool de sous-réseau : %(reason)s." +msgstr "Impossible de supprimer le pool de sous-réseaux : %(reason)s." #, python-format msgid "Unable to determine mac address for %s" @@ -4128,12 +4123,12 @@ msgstr "Impossible de déterminer l'adresse mac pour %s" #, python-format msgid "Unable to find '%s' in request body" -msgstr "Impossible de trouver '%s' dans la corps de demande" +msgstr "Impossible de trouver '%s' dans le corps de demande" #, python-format msgid "Unable to find IP address %(ip_address)s on subnet %(subnet_id)s" msgstr "" -"Impossible de trouver l'adresse IP %(ip_address)s dans le sous réseau " +"Impossible de trouver l'adresse IP %(ip_address)s sur le sous-réseau " "%(subnet_id)s" #, python-format @@ -4189,7 +4184,7 @@ msgid "" "found" msgstr "" "Impossible de vérifier la correspondance %(match)s comme ressource parent : " -"%(res)s n'a pas été trouvée" +"%(res)s introuvable" #, python-format msgid "Unexpected label for script %(script_name)s: %(labels)s" @@ -4212,7 +4207,7 @@ msgid "Unit name '%(unit)s' is not valid." msgstr "Le nom d'unité '%(unit)s' n'est pas valide." msgid "Unknown API version specified" -msgstr "Version de l'API spécifié inconnu" +msgstr "Version d'API spécifiée inconnue" #, python-format msgid "Unknown address type %(address_type)s" @@ -4238,17 +4233,17 @@ msgid "Unmapped error" msgstr "Erreur de non-correspondance" msgid "Unrecognized action" -msgstr "Action inconnu" +msgstr "Action non reconnue" #, python-format msgid "Unrecognized attribute(s) '%s'" msgstr "Attribut(s) non reconnu(s) '%s'" msgid "Unrecognized field" -msgstr "Champ non reconnu" +msgstr "Zone non reconnue" msgid "Unspecified minimum subnet pool prefix." -msgstr "Préfixe de pool de sous-réseau minimum non spécifié." +msgstr "Préfixe de pool de sous-réseaux minimum non spécifié." msgid "Unsupported Content-Type" msgstr "Type de contenu non pris en charge" @@ -4259,7 +4254,7 @@ msgstr "Le type de réseau %(net_type)s n'est pas pris en charge." #, python-format msgid "Unsupported port state: %(port_state)s." -msgstr "L'état du port n'est pas supporté: %(port_state)s." +msgstr "L'état du port n'est pas pris en charge : %(port_state)s." msgid "Unsupported request type" msgstr "Type de demande non pris en charge" @@ -4272,14 +4267,13 @@ msgid "" "improve tunnel scalability." msgstr "" "Utilisez le pilote de mécanisme l2population ML2 pour connaître les adresses " -"MAC et IP et pour améliorer l'évolutivité du tunnel." +"MAC et IP distantes et améliorer l'évolutivité du tunnel." msgid "Use broadcast in DHCP replies." msgstr "Utilisez la diffusion dans les réponses DHCP." msgid "Use either --delta or relative revision, not both" -msgstr "" -"Utiliser soit un --delta, soit une révision relative, mais pas les deux" +msgstr "Utiliser soit --delta, soit une révision relative, mais pas les deux" msgid "" "Use ipset to speed-up the iptables based security groups. Enabling ipset " @@ -4332,7 +4326,7 @@ msgid "" "namespace support (e.g. RHEL 6.5) so long as ovs_use_veth is set to True." msgstr "" "Indique si veth est utilisé ou non pour une interface OVS. Les noyaux avec " -"support limité de l'espace de noms sont pris en charge (par exemple, RHEL " +"support limité de l'espace de nom sont pris en charge (par exemple, RHEL " "6.5) tant que le paramètre ovs_use_veth est défini sur True." msgid "VRRP authentication password" @@ -4342,14 +4336,14 @@ msgid "VRRP authentication type" msgstr "Type d'authentification VRRP" msgid "VXLAN network unsupported." -msgstr "Réseau VXLAN non supporté." +msgstr "Réseau VXLAN non pris en charge." #, python-format msgid "" "Validation of dictionary's keys failed. Expected keys: %(expected_keys)s " "Provided keys: %(provided_keys)s" msgstr "" -"Echec de la validation des clés du dictionnaire. Clés attendues : " +"Echec de validation des clés du dictionnaire. Clés attendues : " "%(expected_keys)s Clés fournies : %(provided_keys)s" #, python-format @@ -4416,7 +4410,7 @@ msgstr "" "tête Instance-ID à l'aide d'un secret partagé afin d'éviter toute " "usurpation. Vous pouvez choisir une chaîne comme secret, mais elle doit être " "identique ici et dans la configuration utilisée par le serveur de " -"métadonnées Nova. REMARQUE : Nova utilise la même clé de configuration, mais " +"métadonnées Nova. REMARQUE : Nova utilise la même clé de configuration, sauf " "dans la section [neutron]." msgid "" @@ -4440,18 +4434,17 @@ msgid "" "through this parameter. " msgstr "" "Avec IPv6, le réseau utilisé pour la passerelle externe ne doit pas " -"obligatoirement disposer d'un sous-réseau associé, étant donné que l'adresse " -"link-local (LLA) automatiquement affectée peut être utilisée. En revanche, " -"une adresse de passerelle IPv6 est nécessaire pour pouvoir faire un saut sur " -"le chemin par défaut. Si aucune adresse de passerelle IPv6 n'estconfigurée " -"dans ce cas, le routeur Neutron sera configuré pour obtenir son chemin par " -"défaut (et uniquement dans ce but) à partir des annonces du routeur en " -"amont ; dans cette situation, le routeur en amont doit être également " -"configuré pour envoyer lesdites annonces. ipv6_gateway, lorsqu'il est " -"configuré, doit constituer la LLA de l'interface du routeur en amont. Si un " -"saut utilisantune adresse unique globale (GUA) est souhaité, il doit être " -"effectué via un sous-réseau attribué au réseau, et non pas par " -"l'intermédiaire de ce paramètre. " +"obligatoirement disposer d'un sous-réseau associé, car l'adresse link-local " +"(LLA) automatiquement affectée peut être utilisée. En revanche, une adresse " +"de passerelle IPv6 est nécessaire pour pouvoir faire un saut sur le chemin " +"par défaut. Si aucune adresse de passerelle IPv6 n'est configurée ici (et " +"uniquement dans ce cas), le routeur Neutron sera configuré pour obtenir son " +"chemin par défaut à partir des annonces du routeur en amont ; dans cette " +"situation, le routeur en amont doit également être configuré pour envoyer " +"lesdites annonces. ipv6_gateway, lorsqu'il est configuré, doit constituer la " +"LLA de l'interface du routeur en amont. Si un saut utilisant une adresse " +"unique globale (GUA) est souhaité, il doit être effectué via un sous-réseau " +"attribué au réseau, et non par l'intermédiaire de ce paramètre. " msgid "You must implement __call__" msgstr "Vous devez implémenter __call__" @@ -4460,14 +4453,14 @@ msgid "" "You must provide a config file for bridge - either --config-file or " "env[NEUTRON_TEST_CONFIG_FILE]" msgstr "" -"Vous devez fournir un fichier de configuration pour le pont --config-file ou " -"env[NEUTRON_TEST_CONFIG_FILE]" +"Vous devez fournir un fichier de configuration pour le pont, --config-file " +"ou env[NEUTRON_TEST_CONFIG_FILE]" msgid "You must provide a revision or relative delta" msgstr "Vous devez fournir une révision ou un delta relatif." msgid "a subnetpool must be specified in the absence of a cidr" -msgstr "Un pool de sous-réseau doit être spécifié en l'absence d'un cidr" +msgstr "Un pool de sous-réseaux doit être spécifié en l'absence d'un cidr" msgid "add_ha_port cannot be called inside of a transaction." msgstr "" @@ -4476,11 +4469,11 @@ msgstr "" msgid "allocation_pools allowed only for specific subnet requests." msgstr "" -"allocation_pools autorisé uniquement pour les requêtes de sous-réseau " +"allocation_pools autorisé uniquement pour les demandes de sous-réseaux " "spécifiques." msgid "allocation_pools are not in the subnet" -msgstr "allocation_pools ne figurent pas dans le sous-réseau" +msgstr "allocation_pools ne figurent pas sur le sous-réseau" msgid "allocation_pools use the wrong ip version" msgstr "allocation_pools utilise une version IP erronée" @@ -4489,7 +4482,7 @@ msgid "already a synthetic attribute" msgstr "déjà un attribut synthétique" msgid "binding:profile value too large" -msgstr "Valeur de liaison:profil excessive" +msgstr "Valeur binding:profile trop grande" #, python-format msgid "cannot perform %(event)s due to %(reason)s" @@ -4513,22 +4506,22 @@ msgstr "Impossible de spécifier une adresse IP fixe sans ID port" #, python-format msgid "gateway_ip %s is not in the subnet" -msgstr "gateway_ip %s ne figure pas dans le sous-réseau" +msgstr "gateway_ip %s ne figure pas sur le sous-réseau" #, python-format msgid "has device owner %s" -msgstr "a le propriétaire de terminal %s" +msgstr "a le propriétaire d'unité %s" msgid "in use" msgstr "utilisé" #, python-format msgid "ip command failed on device %(dev_name)s: %(reason)s" -msgstr "Echec de la commande sur le périphérique %(dev_name)s : %(reason)s" +msgstr "Echec de la commande sur l'unité %(dev_name)s : %(reason)s" #, python-format msgid "ip command failed: %(reason)s" -msgstr "Échec de commande IP : %(reason)s" +msgstr "Echec de commande IP : %(reason)s" #, python-format msgid "ip link capability %(capability)s is not supported" @@ -4552,8 +4545,8 @@ msgid "" "ipv6_ra_mode or ipv6_address_mode cannot be set when enable_dhcp is set to " "False." msgstr "" -"ipv6_ra_mode ou ipv6_address_mode ne peut pas être défini si enable_dhcp a " -"la valeur False." +"ipv6_ra_mode ou ipv6_address_mode ne peut pas être défini quand enable_dhcp " +"a la valeur False." #, python-format msgid "" @@ -4562,7 +4555,7 @@ msgid "" "same value" msgstr "" "ipv6_ra_mode défini sur '%(ra_mode)s' avec ipv6_address_mode défini sur " -"'%(addr_mode)s' n'est pas correct. Si les deux attributs sont définis, ils " +"'%(addr_mode)s' n'est pas admis. Si les deux attributs sont définis, ils " "doivent avoir la même valeur" msgid "mac address update" @@ -4607,11 +4600,10 @@ msgstr "" #, python-format msgid "physical_network '%s' unknown for flat provider network" msgstr "" -"physical_network '%s' inconnu pour le réseau de fournisseurs non hiérarchique" +"physical_network '%s' inconnu pour le réseau de fournisseurs centralisé" msgid "physical_network required for flat provider network" -msgstr "" -"physical_network obligatoire pour le réseau de fournisseurs non hiérarchique" +msgstr "physical_network obligatoire pour le réseau de fournisseurs centralisé" #, python-format msgid "provider:physical_network specified for %s network" @@ -4644,8 +4636,8 @@ msgid "" "subnetpool %(subnetpool_id)s cannot be updated when associated with shared " "address scope %(address_scope_id)s" msgstr "" -"Le pool de sous-réseau %(subnetpool_id)s ne peut pas être mis à jour s'il " -"est associé avec la portée d'adresse partagée %(address_scope_id)s" +"Le pool de sous-réseaux %(subnetpool_id)s ne peut pas être mis à jour s'il " +"est associé à la portée d'adresse partagée %(address_scope_id)s" msgid "subnetpool_id and use_default_subnetpool cannot both be specified" msgstr "" @@ -4666,6 +4658,5 @@ msgid "" "uuid provided from the command line so external_process can track us via /" "proc/cmdline interface." msgstr "" -"Identificateur unique universel fourni dans la ligne de commande afin de " -"permettre à external_process d'effectuer le suivi de l'uuid via l'interface /" -"proc/cmdline." +"UUID fourni dans la ligne de commande afin de permettre à external_process " +"d'effectuer le suivi de l'UUID via l'interface /proc/cmdline." diff --git a/neutron/locale/it/LC_MESSAGES/neutron.po b/neutron/locale/it/LC_MESSAGES/neutron.po index 15d121a8aea..6d78e9228f1 100644 --- a/neutron/locale/it/LC_MESSAGES/neutron.po +++ b/neutron/locale/it/LC_MESSAGES/neutron.po @@ -6,16 +6,17 @@ # OpenStack Infra , 2015. #zanata # Tom Cocozzello , 2015. #zanata # Alessandra , 2016. #zanata +# Remo Mattei , 2016. #zanata # Tom Cocozzello , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.1.dev29\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-04-10 14:30+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-18 20:06+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-03-23 12:29+0000\n" +"PO-Revision-Date: 2016-04-13 09:48+0000\n" "Last-Translator: Alessandra \n" "Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" diff --git a/neutron/locale/ja/LC_MESSAGES/neutron.po b/neutron/locale/ja/LC_MESSAGES/neutron.po index 8d4c5363efb..e65d07232ca 100644 --- a/neutron/locale/ja/LC_MESSAGES/neutron.po +++ b/neutron/locale/ja/LC_MESSAGES/neutron.po @@ -18,14 +18,14 @@ # 笹原 昌美 , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.1.dev29\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-04-10 14:30+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-18 20:06+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-04-04 06:35+0000\n" -"Last-Translator: 笹原 昌美 \n" +"PO-Revision-Date: 2016-04-16 09:56+0000\n" +"Last-Translator: Tsutomu Kimura \n" "Language: ja\n" "Plural-Forms: nplurals=1; plural=0;\n" "Generated-By: Babel 2.0\n" @@ -1246,15 +1246,14 @@ msgstr "ドメイン %(dns_domain)s が外部の DNS サービス内で見つか msgid "Domain to use for building the hostnames" msgstr "ホスト名の作成に使用するドメイン" -#, fuzzy msgid "" "Domain to use for building the hostnames. This option is deprecated. It has " "been moved to neutron.conf as dns_domain. It will be removed in a future " "release." msgstr "" "ホスト名を作成するために使用するドメイン。このオプションは提供を終了していま" -"す。本オプションは、neutron.conf as dns_domain で提供します。将来のリリースに" -"は本オプションは含まれません。" +"す。本オプションは、「neutron.conf as dns_domain」で提供します。将来のリリー" +"スには本オプションは含まれません。" msgid "Downgrade no longer supported" msgstr "ダウングレードは現在ではサポートされていません" @@ -2706,9 +2705,8 @@ msgstr "" "トワークに複数の DHCP エージェントを割り当てるため、DHCP サービスの高可用性が" "実現します。" -#, fuzzy msgid "Number of RPC worker processes dedicated to state reports queue" -msgstr "レポート報告キュー専用の RPC ワーカープロセスの数" +msgstr "レポートのキューを報告するためにのみ機能する RPC ワーカープロセスの数" msgid "Number of RPC worker processes for service" msgstr "RPC サービスのワーカープロセス数" diff --git a/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-error.po b/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-error.po index 151503c6275..6c147e6900b 100644 --- a/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-error.po +++ b/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-error.po @@ -6,9 +6,9 @@ # Sungjin Kang , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.1.dev29\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-04-10 14:30+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-18 20:06+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-info.po b/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-info.po index bd0e986e251..800e41372a2 100644 --- a/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-info.po +++ b/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-info.po @@ -6,9 +6,9 @@ # Sungjin Kang , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.1.dev29\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-04-10 14:30+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-18 20:06+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-warning.po b/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-warning.po index 673bf585a47..3bed1c1dc82 100644 --- a/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-warning.po +++ b/neutron/locale/ko_KR/LC_MESSAGES/neutron-log-warning.po @@ -6,9 +6,9 @@ # Sungjin Kang , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.1.dev1\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-04-07 10:58+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-18 20:06+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -232,14 +232,6 @@ msgstr "인터페이스 삭제 실패: %s" msgid "Failed trying to delete namespace: %s" msgstr "네임스페이스 삭제 실패: %s" -#, python-format -msgid "" -"Firewall driver %(fw_driver)s doesn't accept integration_bridge parameter in " -"__init__(): %(err)s" -msgstr "" -"방화벽 드라이버 %(fw_driver)s이(가) __init__()에서 integration_bridge 매개변" -"수를 허용하지 않음: %(err)s" - #, python-format msgid "Found failed openvswitch port: %s" msgstr "실패한 openvswitch 포트 발견: %s" diff --git a/neutron/locale/ko_KR/LC_MESSAGES/neutron.po b/neutron/locale/ko_KR/LC_MESSAGES/neutron.po index 1f440edaae4..4f8b7489053 100644 --- a/neutron/locale/ko_KR/LC_MESSAGES/neutron.po +++ b/neutron/locale/ko_KR/LC_MESSAGES/neutron.po @@ -15,13 +15,13 @@ # Sungjin Kang , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.1.dev29\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-04-10 14:30+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-18 20:06+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-04-08 12:59+0000\n" +"PO-Revision-Date: 2016-04-11 01:53+0000\n" "Last-Translator: SeYeon Lee \n" "Language: ko-KR\n" "Plural-Forms: nplurals=1; plural=0;\n" @@ -468,7 +468,7 @@ msgid "Allow the usage of the sorting" msgstr "정렬 사용 허용" msgid "Allow to perform insecure SSL (https) requests to nova metadata" -msgstr "nova 메타데이터에 대한 비보안 SSL(https) 요청 수행 허용" +msgstr "Nova 메타데이터에 대한 비보안 SSL(https) 요청 수행 허용" msgid "Allowed address pairs must be a list." msgstr "허용되는 주소 쌍은 목록이어야 합니다. " @@ -645,9 +645,9 @@ msgid "" "information and is useful for debugging issues with either DHCP or DNS. If " "this section is null, disable dnsmasq log." msgstr "" -"dnsmasq 로깅을 위한 기본 로그 디렉토리입니다. 이 로그는 DHCP 및 DNS 로그 정보" -"를 포함하고 있으며 DHCP 또는 DNS에 대한 문제를 디버깅하는 데 유용합니다. 이 " -"섹션이 널인 경우에는 dnsmasq 로그를 사용 안함으로 설정하십시오. " +"dnsmasq 로깅을 위한 기본 로그 디렉토리입니다. 이 로그는 DHCP와 DNS 로그 정보" +"를 포함하고 있으며 DHCP이나 DNS에 대한 문제를 디버깅하는 데 유용합니다. 이 섹" +"션이 널인 경우에는 dnsmasq 로그를 사용 안함으로 설정하십시오. " #, python-format msgid "BgpDrAgent %(agent_id)s is already associated to a BGP speaker." @@ -876,7 +876,7 @@ msgid "Cleanup resources of a specific agent type only." msgstr "특정 에이전트 유형의 자원만 정리합니다." msgid "Client certificate for nova metadata api server." -msgstr "nova 메타데이터 api 서버에 대한 클라이언트 인증서입니다." +msgstr "Nova 메타데이터 api 서버에 대한 클라이언트 인증서입니다." msgid "" "Comma-separated list of : tuples, mapping " @@ -1232,7 +1232,7 @@ msgid "" "defined in the neutron.agent.linux.pd_drivers namespace. See setup.cfg for " "entry points included with the neutron source." msgstr "" -"ipv6 접두부 위임에 사용되는 드라이버입니다. 이는 neutron.agent.linux." +"IPv6 prefix 위임에 사용되는 드라이버입니다. 이는 neutron.agent.linux." "pd_drivers 네임스페이스에서 정의된 시작점이어야 합니다. neutron 소스와 함께 " "포함된 시작점은 setup.cfg를 참조하십시오. " @@ -1752,7 +1752,7 @@ msgid "ID of probe port to execute command" msgstr "명령을 실행할 프로브 포트의 ID" msgid "ID of the router" -msgstr "라우터의 ID" +msgstr "라우터 ID" #, python-format msgid "IP address %(ip)s already allocated in subnet %(subnet_id)s" @@ -2177,7 +2177,7 @@ msgid "Location of Metadata Proxy UNIX domain socket" msgstr "메타데이터 프록시 UNIX 도메인 소켓 위치" msgid "Location of pid file of this process." -msgstr "이 프로세스의 pid 파일 위치입니다." +msgstr "이 프로세스 pid 파일 위치입니다." msgid "Location to store DHCP server config files." msgstr "DHCP 서버 구성 파일을 저장할 위치." @@ -2873,7 +2873,7 @@ msgid "Prefix Delegation can only be used with IPv6 subnets." msgstr "접두부 위임은 IPv6 서브넷에만 사용할 수 있습니다. " msgid "Private key of client certificate." -msgstr "클라이언트 인증서의 개인 키입니다." +msgstr "클라이언트 인증서 개인 키입니다." #, python-format msgid "Probe %s deleted" @@ -2890,7 +2890,7 @@ msgid "Process is not running." msgstr "프로세스가 실행 중이지 않습니다." msgid "Protocol to access nova metadata, http or https" -msgstr "nova 메타데이터에 액세스하기 위한 프로토콜, http 또는 https" +msgstr "Nova 메타데이터에 접근하기 위한 프로토콜, http 또는 https" #, python-format msgid "Provider name %(name)s is limited by %(len)s characters" @@ -3147,7 +3147,7 @@ msgstr "" "%(records)s." msgid "Run as daemon." -msgstr "디먼으로 실행됩니다." +msgstr "데몬으로 실행됩니다." #, python-format msgid "Running %(cmd)s (%(desc)s) for %(project)s ..." @@ -3353,7 +3353,7 @@ msgstr "" "자만 대체할 수 있습니다." msgid "TCP Port to listen for metadata server requests." -msgstr "메타데이터 서버 요청을 청취할 TCP 포트입니다. " +msgstr "메타데이터 서버 요청을 listen TCP 포트입니다. " msgid "TCP Port used by Neutron metadata namespace proxy." msgstr "Neutron 메타데이터 네임스페이스 프록시가 사용하는 TCP 포트입니다. " @@ -3444,7 +3444,7 @@ msgid "" msgstr "다음 원인으로 인해 주소 할당 요청을 충족할 수 없음: %(reason)s" msgid "The advertisement interval in seconds" -msgstr "광고 간격(초)" +msgstr "Advertisement 간격(초)" #, python-format msgid "The allocation pool %(pool)s is not valid." @@ -4109,10 +4109,10 @@ msgid "" "Server. NOTE: Nova uses the same config key, but in [neutron] section." msgstr "" "메타데이터 요청의 프록시 역할을 수행할 때 Neutron이 위조를 방지하기 위해 공" -"유 시크릿으로 Instance-ID 헤더에 서명합니다. 시크릿으로 임의의 문자열을 선택" -"할 수 있지만 여기에 있는 문자열 및 Nova Metadata Server에서 사용하는 구성과 " -"일치해야 합니다. 참고: Nova에서는 [neutron] 섹션에 있는 동일한 구성 키를 사용" -"합니다." +"유 시크릿으로 Instance-ID 헤더에 서명합니다. Secret으로 임의의 문자열을 선택" +"할 수 있지만 여기에 있는 문자열와 Nova Metadata Server에서 사용하는 구성과 일" +"치해야 합니다. 참고: Nova에서는 [neutron] 섹션에 있는 동일한 구성 키를 사용합" +"니다." msgid "" "Where to store Neutron state files. This directory must be writable by the " diff --git a/neutron/locale/neutron-log-error.pot b/neutron/locale/neutron-log-error.pot index 42b514253ae..cb0df341e33 100644 --- a/neutron/locale/neutron-log-error.pot +++ b/neutron/locale/neutron-log-error.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0rc2.dev12\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-22 06:02+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-19 06:52+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -47,22 +47,22 @@ msgstr "" msgid "Exception occurs when waiting for timer" msgstr "" -#: neutron/wsgi.py:142 +#: neutron/wsgi.py:144 #, python-format msgid "Unable to listen on %(host)s:%(port)s" msgstr "" -#: neutron/wsgi.py:601 +#: neutron/wsgi.py:603 #, python-format msgid "InvalidContentType: %s" msgstr "" -#: neutron/wsgi.py:605 +#: neutron/wsgi.py:607 #, python-format msgid "MalformedRequestBody: %s" msgstr "" -#: neutron/wsgi.py:614 +#: neutron/wsgi.py:616 msgid "Internal error" msgstr "" @@ -106,11 +106,11 @@ msgstr "" msgid "Network %s info call failed." msgstr "" -#: neutron/agent/dhcp/agent.py:595 neutron/agent/l3/agent.py:691 +#: neutron/agent/dhcp/agent.py:595 neutron/agent/l3/agent.py:697 #: neutron/agent/metadata/agent.py:275 -#: neutron/plugins/ml2/drivers/agent/_common_agent.py:128 -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:178 -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:327 +#: neutron/plugins/ml2/drivers/agent/_common_agent.py:130 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:182 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:326 #: neutron/services/bgp/agent/bgp_dragent.py:695 #: neutron/services/metering/agents/metering_agent.py:284 msgid "Failed reporting state!" @@ -130,51 +130,51 @@ msgstr "" msgid "An interface driver must be specified" msgstr "" -#: neutron/agent/l3/agent.py:270 +#: neutron/agent/l3/agent.py:276 #, python-format msgid "%s used in config as ipv6_gateway is not a valid IPv6 link-local address." msgstr "" -#: neutron/agent/l3/agent.py:357 +#: neutron/agent/l3/agent.py:363 #, python-format msgid "Error while deleting router %s" msgstr "" -#: neutron/agent/l3/agent.py:412 +#: neutron/agent/l3/agent.py:418 #, python-format msgid "The external network bridge '%s' does not exist" msgstr "" -#: neutron/agent/l3/agent.py:475 +#: neutron/agent/l3/agent.py:481 #, python-format msgid "Failed to fetch router information for '%s'" msgstr "" -#: neutron/agent/l3/agent.py:502 +#: neutron/agent/l3/agent.py:508 #, python-format msgid "Removing incompatible router '%s'" msgstr "" -#: neutron/agent/l3/agent.py:506 +#: neutron/agent/l3/agent.py:512 #, python-format msgid "Failed to process compatible router '%s'" msgstr "" -#: neutron/agent/l3/agent.py:579 +#: neutron/agent/l3/agent.py:585 #, python-format msgid "" "Server failed to return info for routers in required time, decreasing " "chunk size to: %s" msgstr "" -#: neutron/agent/l3/agent.py:583 +#: neutron/agent/l3/agent.py:589 #, python-format msgid "" "Server failed to return info for routers in required time even with min " "chunk size: %s. It might be under very high load or just inoperable" msgstr "" -#: neutron/agent/l3/agent.py:590 +#: neutron/agent/l3/agent.py:596 msgid "Failed synchronizing routers due to RPC error" msgstr "" @@ -283,12 +283,12 @@ msgstr "" msgid "Error while create dnsmasq log dir: %s" msgstr "" -#: neutron/agent/linux/dhcp.py:1237 +#: neutron/agent/linux/dhcp.py:1236 #, python-format msgid "Unable to plug DHCP port for network %s. Releasing port." msgstr "" -#: neutron/agent/linux/dhcp.py:1274 +#: neutron/agent/linux/dhcp.py:1273 msgid "Exception during stale dhcp device cleanup" msgstr "" @@ -367,7 +367,12 @@ msgid "" "%s" msgstr "" -#: neutron/agent/linux/ovsdb_monitor.py:74 +#: neutron/agent/linux/keepalived.py:376 +#, python-format +msgid "Could not delete file %s, keepalived can refuse to start." +msgstr "" + +#: neutron/agent/linux/ovsdb_monitor.py:75 msgid "Interface monitor is not active" msgstr "" @@ -376,7 +381,7 @@ msgstr "" msgid "Unable to convert value in %s" msgstr "" -#: neutron/agent/linux/openvswitch_firewall/firewall.py:224 +#: neutron/agent/linux/openvswitch_firewall/firewall.py:273 #, python-format msgid "Initializing port %s that was already initialized." msgstr "" @@ -404,18 +409,18 @@ msgstr "" msgid "Failed to get ip addresses for interface: %s." msgstr "" -#: neutron/api/extensions.py:476 +#: neutron/api/extensions.py:478 #, python-format msgid "" "Unable to process extensions (%s) because the configured plugins do not " "satisfy their requirements. Some features will not work as expected." msgstr "" -#: neutron/api/extensions.py:500 +#: neutron/api/extensions.py:502 msgid "Exception loading extension" msgstr "" -#: neutron/api/extensions.py:519 +#: neutron/api/extensions.py:521 #, python-format msgid "Extension path '%s' doesn't exist!" msgstr "" @@ -607,19 +612,19 @@ msgstr "" msgid "Unexpected exception occurred." msgstr "" -#: neutron/common/utils.py:526 +#: neutron/common/utils.py:537 msgid "Alias or class name is not set" msgstr "" -#: neutron/common/utils.py:538 +#: neutron/common/utils.py:549 msgid "Error loading class by alias" msgstr "" -#: neutron/common/utils.py:540 +#: neutron/common/utils.py:551 msgid "Error loading class by class name" msgstr "" -#: neutron/db/agents_db.py:492 +#: neutron/db/agents_db.py:506 #, python-format msgid "" "Message received from the host: %(host)s during the registration of " @@ -633,14 +638,14 @@ msgstr "" msgid "Failed to schedule network %s" msgstr "" -#: neutron/db/agentschedulers_db.py:316 +#: neutron/db/agentschedulers_db.py:315 #, python-format msgid "" "Unexpected exception occurred while removing network %(net)s from agent " "%(agent)s" msgstr "" -#: neutron/db/agentschedulers_db.py:327 +#: neutron/db/agentschedulers_db.py:326 msgid "Exception encountered during network rescheduling" msgstr "" @@ -649,7 +654,7 @@ msgstr "" msgid "Cannot clean up created object %(obj)s. Exception: %(exc)s" msgstr "" -#: neutron/db/db_base_plugin_v2.py:303 neutron/plugins/ml2/plugin.py:655 +#: neutron/db/db_base_plugin_v2.py:303 neutron/plugins/ml2/plugin.py:631 #, python-format msgid "An exception occurred while creating the %(resource)s:%(item)s" msgstr "" @@ -708,12 +713,12 @@ msgid "" "changes" msgstr "" -#: neutron/db/l3_agentschedulers_db.py:134 +#: neutron/db/l3_agentschedulers_db.py:141 #, python-format msgid "Failed to reschedule router %s" msgstr "" -#: neutron/db/l3_agentschedulers_db.py:139 +#: neutron/db/l3_agentschedulers_db.py:146 msgid "Exception encountered during router rescheduling." msgstr "" @@ -763,7 +768,7 @@ msgid "An unexpected exception was caught: %s" msgstr "" #: neutron/plugins/ml2/db.py:242 neutron/plugins/ml2/db.py:326 -#: neutron/plugins/ml2/plugin.py:1490 +#: neutron/plugins/ml2/plugin.py:1466 #, python-format msgid "Multiple ports have port_id starting with %s" msgstr "" @@ -824,102 +829,102 @@ msgstr "" msgid "Extension driver '%(name)s' failed in %(method)s" msgstr "" -#: neutron/plugins/ml2/plugin.py:364 +#: neutron/plugins/ml2/plugin.py:340 #, python-format msgid "Failed to commit binding results for %(port)s after %(max)s tries" msgstr "" -#: neutron/plugins/ml2/plugin.py:536 +#: neutron/plugins/ml2/plugin.py:512 #, python-format msgid "Serialized vif_details DB value '%(value)s' for port %(port)s is invalid" msgstr "" -#: neutron/plugins/ml2/plugin.py:547 +#: neutron/plugins/ml2/plugin.py:523 #, python-format msgid "Serialized profile DB value '%(value)s' for port %(port)s is invalid" msgstr "" -#: neutron/plugins/ml2/plugin.py:632 +#: neutron/plugins/ml2/plugin.py:608 #, python-format msgid "Could not find %s to delete." msgstr "" -#: neutron/plugins/ml2/plugin.py:635 +#: neutron/plugins/ml2/plugin.py:611 #, python-format msgid "Could not delete %(res)s %(id)s." msgstr "" -#: neutron/plugins/ml2/plugin.py:668 +#: neutron/plugins/ml2/plugin.py:644 #, python-format msgid "" "mechanism_manager.create_%(res)s_postcommit failed for %(res)s: " "'%(failed_id)s'. Deleting %(res)ss %(resource_ids)s" msgstr "" -#: neutron/plugins/ml2/plugin.py:724 +#: neutron/plugins/ml2/plugin.py:700 #, python-format msgid "mechanism_manager.create_network_postcommit failed, deleting network '%s'" msgstr "" -#: neutron/plugins/ml2/plugin.py:801 +#: neutron/plugins/ml2/plugin.py:777 #, python-format msgid "Exception auto-deleting port %s" msgstr "" -#: neutron/plugins/ml2/plugin.py:813 +#: neutron/plugins/ml2/plugin.py:789 #, python-format msgid "Exception auto-deleting subnet %s" msgstr "" -#: neutron/plugins/ml2/plugin.py:898 +#: neutron/plugins/ml2/plugin.py:874 msgid "mechanism_manager.delete_network_postcommit failed" msgstr "" -#: neutron/plugins/ml2/plugin.py:921 +#: neutron/plugins/ml2/plugin.py:897 #, python-format msgid "mechanism_manager.create_subnet_postcommit failed, deleting subnet '%s'" msgstr "" -#: neutron/plugins/ml2/plugin.py:1049 +#: neutron/plugins/ml2/plugin.py:1025 #, python-format msgid "Exception deleting fixed_ip from port %s" msgstr "" -#: neutron/plugins/ml2/plugin.py:1058 +#: neutron/plugins/ml2/plugin.py:1034 msgid "mechanism_manager.delete_subnet_postcommit failed" msgstr "" -#: neutron/plugins/ml2/plugin.py:1124 +#: neutron/plugins/ml2/plugin.py:1100 #, python-format msgid "mechanism_manager.create_port_postcommit failed, deleting port '%s'" msgstr "" -#: neutron/plugins/ml2/plugin.py:1143 +#: neutron/plugins/ml2/plugin.py:1119 #, python-format msgid "_bind_port_if_needed failed, deleting port '%s'" msgstr "" -#: neutron/plugins/ml2/plugin.py:1172 +#: neutron/plugins/ml2/plugin.py:1148 #, python-format msgid "_bind_port_if_needed failed. Deleting all ports from create bulk '%s'" msgstr "" -#: neutron/plugins/ml2/plugin.py:1312 +#: neutron/plugins/ml2/plugin.py:1288 #, python-format msgid "mechanism_manager.update_port_postcommit failed for port %s" msgstr "" -#: neutron/plugins/ml2/plugin.py:1359 +#: neutron/plugins/ml2/plugin.py:1335 #, python-format msgid "No Host supplied to bind DVR Port %s" msgstr "" -#: neutron/plugins/ml2/plugin.py:1471 +#: neutron/plugins/ml2/plugin.py:1447 #, python-format msgid "mechanism_manager.delete_port_postcommit failed for port %s" msgstr "" -#: neutron/plugins/ml2/plugin.py:1503 +#: neutron/plugins/ml2/plugin.py:1479 #, python-format msgid "Binding info for DVR port %s not found" msgstr "" @@ -939,6 +944,11 @@ msgstr "" msgid "Failed to update device %s down" msgstr "" +#: neutron/plugins/ml2/drivers/helpers.py:43 +#, python-format +msgid "Failed to parse physical_network_mtus: %s" +msgstr "" + #: neutron/plugins/ml2/drivers/type_geneve.py:90 #: neutron/plugins/ml2/drivers/type_vxlan.py:85 msgid "Failed to parse vni_ranges. Service terminated!" @@ -958,24 +968,24 @@ msgid "" "CommonAgent works properly." msgstr "" -#: neutron/plugins/ml2/drivers/agent/_common_agent.py:133 +#: neutron/plugins/ml2/drivers/agent/_common_agent.py:135 msgid "" "RPC Callback class must inherit from CommonAgentManagerRpcCallBackBase to" " ensure CommonAgent works properly." msgstr "" -#: neutron/plugins/ml2/drivers/agent/_common_agent.py:209 +#: neutron/plugins/ml2/drivers/agent/_common_agent.py:211 #, python-format msgid "Unable to get port details for %s" msgstr "" -#: neutron/plugins/ml2/drivers/agent/_common_agent.py:308 +#: neutron/plugins/ml2/drivers/agent/_common_agent.py:310 #, python-format msgid "Error occurred while removing port %s" msgstr "" -#: neutron/plugins/ml2/drivers/agent/_common_agent.py:419 -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:381 +#: neutron/plugins/ml2/drivers/agent/_common_agent.py:421 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:385 #, python-format msgid "Error in agent loop. Devices info: %s" msgstr "" @@ -1050,22 +1060,22 @@ msgstr "" msgid "Unknown network_type %(network_type)s for network %(network_id)s." msgstr "" -#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:584 +#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:594 msgid "No valid Segmentation ID to perform UCAST test." msgstr "" -#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:688 +#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:698 #: neutron/plugins/ml2/drivers/macvtap/agent/macvtap_neutron_agent.py:120 msgid "Unable to obtain MAC address for unique ID. Agent terminated!" msgstr "" -#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:874 +#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:884 #: neutron/plugins/ml2/drivers/macvtap/agent/macvtap_neutron_agent.py:182 #, python-format msgid "Parsing physical_interface_mappings failed: %s. Agent terminated!" msgstr "" -#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:883 +#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:893 #, python-format msgid "Parsing bridge_mappings failed: %s. Agent terminated!" msgstr "" @@ -1088,7 +1098,7 @@ msgstr "" msgid "Failed to get devices for %s" msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/eswitch_manager.py:392 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/eswitch_manager.py:393 #, python-format msgid "PCI slot %(pci_slot)s has no mapping to Embedded Switch; skipping" msgstr "" @@ -1098,11 +1108,11 @@ msgstr "" msgid "Failed executing ip command: %s" msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:441 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:446 msgid "Failed on Agent configuration parse. Agent terminated!" msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:453 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:458 msgid "Agent Initialization Failed" msgstr "" @@ -1139,114 +1149,114 @@ msgid "" "a different subnet %(orig_subnet)s" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:465 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:464 msgid "No tunnel_type specified, cannot create tunnels" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:468 -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:493 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:467 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:492 #, python-format msgid "tunnel_type %s not supported by agent" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:486 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:485 msgid "No tunnel_ip specified, cannot delete tunnels" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:490 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:489 msgid "No tunnel_type specified, cannot delete tunnels" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:638 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:637 #, python-format msgid "No local VLAN available for net-id=%s" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:669 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:668 #, python-format msgid "" "Cannot provision %(network_type)s network for net-id=%(net_uuid)s - " "tunneling disabled" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:677 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:676 #, python-format msgid "" "Cannot provision flat network for net-id=%(net_uuid)s - no bridge for " "physical_network %(physical_network)s" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:687 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:686 #, python-format msgid "" "Cannot provision VLAN network for net-id=%(net_uuid)s - no bridge for " "physical_network %(physical_network)s" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:696 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:695 #, python-format msgid "" "Cannot provision unknown network type %(network_type)s for net-" "id=%(net_uuid)s" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:756 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:755 #, python-format msgid "" "Cannot reclaim unknown network type %(network_type)s for net-" "id=%(net_uuid)s" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:794 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:793 #, python-format msgid "Expected port %s not found" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:878 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:877 #, python-format msgid "Configuration for devices %s failed!" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1044 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1047 msgid "" "Failed to create OVS patch port. Cannot have tunneling enabled on this " "agent, since this version of OVS does not support tunnels or patch ports." " Agent terminated!" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1081 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1084 #, python-format msgid "" "Bridge %(bridge)s for physical network %(physical_network)s does not " "exist. Agent terminated!" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1398 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1401 #, python-format msgid "Failed to set-up %(type)s tunnel port to %(ip)s" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1931 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1934 msgid "Error while configuring tunnel endpoints" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:2007 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:2010 msgid "Error while processing VIF ports" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:2065 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:2068 #, python-format msgid "" "Tunneling can't be enabled with invalid local_ip '%s'. IP couldn't be " "found on this host's interfaces." msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:2079 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:2082 #, python-format msgid "Invalid tunnel type specified: %s" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:2099 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:2102 #, python-format msgid "%s Agent terminated!" msgstr "" @@ -1289,7 +1299,7 @@ msgstr "" msgid "Model class %s does not have a tenant_id attribute" msgstr "" -#: neutron/scheduler/l3_agent_scheduler.py:253 +#: neutron/scheduler/l3_agent_scheduler.py:254 #, python-format msgid "Not enough candidates, a HA router needs at least %s agents" msgstr "" @@ -1402,7 +1412,7 @@ msgstr "" msgid "Driver %(driver)s:%(func)s runtime error" msgstr "" -#: neutron/services/metering/drivers/iptables/iptables_driver.py:356 +#: neutron/services/metering/drivers/iptables/iptables_driver.py:357 #, python-format msgid "Failed to get traffic counters, router: %s" msgstr "" diff --git a/neutron/locale/neutron-log-info.pot b/neutron/locale/neutron-log-info.pot index 378fc4e3dc9..faf7013cab7 100644 --- a/neutron/locale/neutron-log-info.pot +++ b/neutron/locale/neutron-log-info.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0b4.dev136\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-12 06:02+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-19 06:52+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -37,22 +37,22 @@ msgstr "" msgid "Neutron service started, listening on %(host)s:%(port)s" msgstr "" -#: neutron/wsgi.py:594 +#: neutron/wsgi.py:596 #, python-format msgid "%(method)s %(url)s" msgstr "" -#: neutron/wsgi.py:611 +#: neutron/wsgi.py:613 #, python-format msgid "HTTP exception thrown: %s" msgstr "" -#: neutron/wsgi.py:627 +#: neutron/wsgi.py:629 #, python-format msgid "%(url)s returned with HTTP %(status)d" msgstr "" -#: neutron/wsgi.py:630 +#: neutron/wsgi.py:632 #, python-format msgid "%(url)s returned a fault: %(exception)s" msgstr "" @@ -65,42 +65,42 @@ msgstr "" msgid "Disabled allowed-address-pairs extension." msgstr "" -#: neutron/agent/securitygroups_rpc.py:147 +#: neutron/agent/securitygroups_rpc.py:142 #, python-format msgid "" "Skipping method %s as firewall is disabled or configured as " "NoopFirewallDriver." msgstr "" -#: neutron/agent/securitygroups_rpc.py:159 +#: neutron/agent/securitygroups_rpc.py:154 #, python-format msgid "Preparing filters for devices %s" msgstr "" -#: neutron/agent/securitygroups_rpc.py:189 +#: neutron/agent/securitygroups_rpc.py:184 #, python-format msgid "Security group rule updated %r" msgstr "" -#: neutron/agent/securitygroups_rpc.py:197 +#: neutron/agent/securitygroups_rpc.py:192 #, python-format msgid "Security group member updated %r" msgstr "" -#: neutron/agent/securitygroups_rpc.py:222 +#: neutron/agent/securitygroups_rpc.py:217 msgid "Provider rule updated" msgstr "" -#: neutron/agent/securitygroups_rpc.py:234 +#: neutron/agent/securitygroups_rpc.py:229 #, python-format msgid "Remove device filter for %r" msgstr "" -#: neutron/agent/securitygroups_rpc.py:244 +#: neutron/agent/securitygroups_rpc.py:239 msgid "Refresh firewall rules" msgstr "" -#: neutron/agent/securitygroups_rpc.py:248 +#: neutron/agent/securitygroups_rpc.py:243 msgid "No ports here to refresh firewall" msgstr "" @@ -145,7 +145,7 @@ msgstr "" msgid "Agent has just been revived. Scheduling full sync" msgstr "" -#: neutron/agent/dhcp/agent.py:604 neutron/agent/l3/agent.py:704 +#: neutron/agent/dhcp/agent.py:604 neutron/agent/l3/agent.py:710 #: neutron/services/bgp/agent/bgp_dragent.py:704 #: neutron/services/metering/agents/metering_agent.py:287 #, python-format @@ -176,12 +176,12 @@ msgid "" "trying to reset" msgstr "" -#: neutron/agent/l3/agent.py:617 neutron/agent/l3/agent.py:695 +#: neutron/agent/l3/agent.py:623 neutron/agent/l3/agent.py:701 msgid "L3 agent started" msgstr "" -#: neutron/agent/l3/agent.py:680 -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:319 +#: neutron/agent/l3/agent.py:686 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:315 msgid "Agent has just been revived. Doing a full sync." msgstr "" @@ -202,14 +202,14 @@ msgstr "" msgid "Process runs with uid/gid: %(uid)s/%(gid)s" msgstr "" -#: neutron/agent/linux/dhcp.py:860 +#: neutron/agent/linux/dhcp.py:859 #, python-format msgid "" "Cannot apply dhcp option %(opt)s because it's ip_version %(version)d is " "not in port's address IP versions" msgstr "" -#: neutron/agent/linux/dhcp.py:1134 +#: neutron/agent/linux/dhcp.py:1133 #, python-format msgid "Skipping DHCP port %s as it is already in use" msgstr "" @@ -229,11 +229,11 @@ msgstr "" msgid "Attempted to remove port filter which is not filtered %r" msgstr "" -#: neutron/api/extensions.py:407 +#: neutron/api/extensions.py:409 msgid "Initializing extension manager." msgstr "" -#: neutron/api/extensions.py:553 +#: neutron/api/extensions.py:555 #, python-format msgid "Loaded extension: %s" msgstr "" @@ -312,7 +312,7 @@ msgstr "" msgid "IPv6 is not enabled on this system." msgstr "" -#: neutron/db/agents_db.py:318 +#: neutron/db/agents_db.py:319 #, python-format msgid "" "Heartbeat received from %(type)s agent on host %(host)s, uuid %(uuid)s " @@ -342,7 +342,7 @@ msgstr "" msgid "Adding network %(net)s to agent %(agent)s on host %(host)s" msgstr "" -#: neutron/db/db_base_plugin_v2.py:868 neutron/plugins/ml2/plugin.py:976 +#: neutron/db/db_base_plugin_v2.py:872 neutron/plugins/ml2/plugin.py:974 #, python-format msgid "" "Found port (%(port_id)s, %(ip)s) having IP allocation on subnet " @@ -381,7 +381,7 @@ msgid "" "rescheduling is disabled." msgstr "" -#: neutron/db/l3_db.py:1409 +#: neutron/db/l3_db.py:1413 #, python-format msgid "Skipping port %s as no IP is configure on it" msgstr "" @@ -391,12 +391,12 @@ msgstr "" msgid "Centralizing distributed router %s is not supported" msgstr "" -#: neutron/db/l3_dvr_db.py:587 +#: neutron/db/l3_dvr_db.py:629 #, python-format msgid "Agent Gateway port does not exist, so create one: %s" msgstr "" -#: neutron/db/l3_dvr_db.py:669 +#: neutron/db/l3_dvr_db.py:711 #, python-format msgid "SNAT interface port list does not exist, so create one: %s" msgstr "" @@ -408,19 +408,19 @@ msgid "" "router %(router)s" msgstr "" -#: neutron/db/l3_hamode_db.py:311 +#: neutron/db/l3_hamode_db.py:322 #, python-format msgid "" "Number of active agents lower than max_l3_agents_per_router. L3 agents " "available: %s" msgstr "" -#: neutron/db/l3_hamode_db.py:554 +#: neutron/db/l3_hamode_db.py:574 #, python-format msgid "HA network %s can not be deleted." msgstr "" -#: neutron/db/l3_hamode_db.py:560 +#: neutron/db/l3_hamode_db.py:580 #, python-format msgid "" "HA network %(network)s was deleted as no HA routers are present in tenant" @@ -556,22 +556,22 @@ msgstr "" msgid "Attempt %(count)s to bind port %(port)s" msgstr "" -#: neutron/plugins/ml2/plugin.py:778 +#: neutron/plugins/ml2/plugin.py:774 #, python-format msgid "Port %s was deleted concurrently" msgstr "" -#: neutron/plugins/ml2/plugin.py:789 +#: neutron/plugins/ml2/plugin.py:785 #, python-format msgid "Subnet %s was deleted concurrently" msgstr "" -#: neutron/plugins/ml2/plugin.py:1466 +#: neutron/plugins/ml2/plugin.py:1462 #, python-format msgid "No ports have port_id starting with %s" msgstr "" -#: neutron/plugins/ml2/plugin.py:1496 +#: neutron/plugins/ml2/plugin.py:1492 #, python-format msgid "" "Binding info for port %s was not found, it might have been deleted " @@ -630,47 +630,47 @@ msgstr "" msgid "%s Agent has just been revived. Doing a full sync." msgstr "" -#: neutron/plugins/ml2/drivers/agent/_common_agent.py:145 -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:147 +#: neutron/plugins/ml2/drivers/agent/_common_agent.py:147 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:148 #, python-format msgid "RPC agent_id: %s" msgstr "" -#: neutron/plugins/ml2/drivers/agent/_common_agent.py:218 -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:295 -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1472 +#: neutron/plugins/ml2/drivers/agent/_common_agent.py:220 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:299 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1474 #, python-format msgid "Port %(device)s updated. Details: %(details)s" msgstr "" -#: neutron/plugins/ml2/drivers/agent/_common_agent.py:292 +#: neutron/plugins/ml2/drivers/agent/_common_agent.py:294 #, python-format msgid "Device %s not defined on plugin" msgstr "" -#: neutron/plugins/ml2/drivers/agent/_common_agent.py:300 +#: neutron/plugins/ml2/drivers/agent/_common_agent.py:302 #, python-format msgid "Attachment %s removed" msgstr "" -#: neutron/plugins/ml2/drivers/agent/_common_agent.py:312 -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1558 +#: neutron/plugins/ml2/drivers/agent/_common_agent.py:314 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1560 #, python-format msgid "Port %s updated." msgstr "" -#: neutron/plugins/ml2/drivers/agent/_common_agent.py:395 +#: neutron/plugins/ml2/drivers/agent/_common_agent.py:397 #, python-format msgid "%s Agent RPC Daemon Started!" msgstr "" -#: neutron/plugins/ml2/drivers/agent/_common_agent.py:407 +#: neutron/plugins/ml2/drivers/agent/_common_agent.py:409 #, python-format msgid "%s Agent out of sync with plugin!" msgstr "" #: neutron/plugins/ml2/drivers/linuxbridge/agent/arp_protect.py:33 -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:889 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:887 #, python-format msgid "" "Skipping ARP spoofing rules for port '%s' because it has port security " @@ -682,26 +682,26 @@ msgstr "" msgid "Clearing orphaned ARP spoofing entries for devices %s" msgstr "" -#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:756 +#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:766 #, python-format msgid "Physical network %s is defined in bridge_mappings and cannot be deleted." msgstr "" -#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:877 +#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:887 #: neutron/plugins/ml2/drivers/macvtap/agent/macvtap_neutron_agent.py:179 #, python-format msgid "Interface mappings: %s" msgstr "" -#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:886 +#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:896 #, python-format msgid "Bridge mappings: %s" msgstr "" -#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:895 +#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:905 #: neutron/plugins/ml2/drivers/macvtap/agent/macvtap_neutron_agent.py:214 -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:456 -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:2017 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:461 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:2019 msgid "Agent initialized successfully, now running... " msgstr "" @@ -709,47 +709,47 @@ msgstr "" msgid "Initializing Linux bridge QoS extension" msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:237 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:241 #, python-format msgid "Device %(device)s spoofcheck %(spoofcheck)s" msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:261 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:265 #: neutron/plugins/ml2/drivers/mech_sriov/agent/extension_drivers/qos_driver.py:65 #, python-format msgid "No device with MAC %s defined on agent." msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:309 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:313 #, python-format msgid "Device with MAC %s not defined on plugin" msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:317 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:321 #, python-format msgid "Removing device with MAC address %(mac)s and PCI slot %(pci_slot)s" msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:342 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:346 #, python-format msgid "Port with MAC %(mac)s and PCI slot %(pci_slot)s updated." msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:355 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:359 msgid "SRIOV NIC Agent RPC Daemon Started!" msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:362 -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1760 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:366 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1762 msgid "Agent out of sync with plugin!" msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:444 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:449 #, python-format msgid "Physical Devices mappings: %s" msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:445 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:450 #, python-format msgid "Exclude Devices: %s" msgstr "" @@ -759,91 +759,96 @@ msgstr "" msgid "L2 Agent operating in DVR Mode with MAC %s" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:648 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_dvr_neutron_agent.py:577 +#, python-format +msgid "DVR: Port %(vif)s changed port number to %(ofport)s, rebinding." +msgstr "" + +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:646 #, python-format msgid "Assigning %(vlan_id)s as local vlan for net-id=%(net_uuid)s" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:712 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:710 #, python-format msgid "Reclaiming vlan = %(vlan_id)s from net-id = %(net_uuid)s" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:881 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:879 #, python-format msgid "Configuration for devices up %(up)s and devices down %(down)s completed." msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:948 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:946 #, python-format msgid "port_unbound(): net_uuid %s not in local_vlan_map" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1014 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1016 #, python-format msgid "Adding %s to list of bridges." msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1076 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1078 #, python-format msgid "Mapping physical network %(physical_network)s to bridge %(bridge)s" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1354 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1356 #, python-format msgid "Port '%(port_name)s' has lost its vlan tag '%(vlan_tag)d'!" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1381 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1383 #, python-format msgid "VIF port: %s admin state up disabled, putting on the dead VLAN" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1466 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1468 #, python-format msgid "" "Port %s was not found on the integration bridge and will therefore not be" " processed" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1526 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1528 #, python-format msgid "Ancillary Ports %(added)s added, failed devices %(failed)s" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1533 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1535 #, python-format msgid "Ports %s removed" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1546 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1548 #, python-format msgid "Ancillary ports %s removed" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1552 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1554 #, python-format msgid "Devices down %s " msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1656 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1658 msgid "Configuring tunnel endpoints to other OVS agents" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1747 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1749 #, python-format msgid "Cleaning stale %s flows" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1886 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1888 msgid "rpc_loop doing a full sync." msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:2037 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:2039 msgid "Agent caught SIGTERM, quitting daemon loop." msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:2041 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:2043 msgid "Agent caught SIGHUP, resetting." msgstr "" @@ -1002,7 +1007,7 @@ msgstr "" msgid "Loading Metering driver %s" msgstr "" -#: neutron/services/metering/drivers/iptables/iptables_driver.py:89 +#: neutron/services/metering/drivers/iptables/iptables_driver.py:90 #, python-format msgid "Loading interface driver %s" msgstr "" diff --git a/neutron/locale/neutron-log-warning.pot b/neutron/locale/neutron-log-warning.pot index 4ef6505e9a6..37e49e3e3fc 100644 --- a/neutron/locale/neutron-log-warning.pot +++ b/neutron/locale/neutron-log-warning.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0b4.dev136\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-12 06:02+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-19 06:52+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,7 +17,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.2.0\n" -#: neutron/policy.py:112 +#: neutron/policy.py:115 #, python-format msgid "Unable to find data type descriptor for attribute %s" msgstr "" @@ -35,14 +35,7 @@ msgstr "" msgid "Driver configuration doesn't match with enable_security_group" msgstr "" -#: neutron/agent/securitygroups_rpc.py:107 -#, python-format -msgid "" -"Firewall driver %(fw_driver)s doesn't accept integration_bridge parameter" -" in __init__(): %(err)s" -msgstr "" - -#: neutron/agent/securitygroups_rpc.py:135 +#: neutron/agent/securitygroups_rpc.py:130 msgid "" "security_group_info_for_devices rpc call not supported by the server, " "falling back to old security_group_rules_for_devices which scales worse." @@ -85,7 +78,7 @@ msgid "" "port %(port_id)s, for router %(router_id)s will be considered" msgstr "" -#: neutron/agent/dhcp/agent.py:589 neutron/agent/l3/agent.py:686 +#: neutron/agent/dhcp/agent.py:589 neutron/agent/l3/agent.py:692 #: neutron/agent/metadata/agent.py:270 #: neutron/services/bgp/agent/bgp_dragent.py:689 #: neutron/services/metering/agents/metering_agent.py:279 @@ -115,12 +108,19 @@ msgid "" "Retrying. Detail message: %s" msgstr "" -#: neutron/agent/l3/agent.py:365 +#: neutron/agent/l3/agent.py:267 +msgid "" +"Using an 'external_network_bridge' value other than '' is deprecated. Any" +" other values may not be supported in the future. Note that the default " +"value is 'br-ex' so it must be explicitly set to a blank value." +msgstr "" + +#: neutron/agent/l3/agent.py:371 #, python-format msgid "Info for router %s was not found. Performing router cleanup" msgstr "" -#: neutron/agent/l3/dvr_local_router.py:212 +#: neutron/agent/l3/dvr_local_router.py:214 #, python-format msgid "" "Device %s does not exist so ARP entry cannot be updated, will cache " @@ -172,6 +172,11 @@ msgstr "" msgid "Attempted to get traffic counters of chain %s which does not exist" msgstr "" +#: neutron/agent/linux/openvswitch_firewall/firewall.py:252 +#, python-format +msgid "Can't get tag for port %(port_id)s from its other_config: %(other_config)s" +msgstr "" + #: neutron/agent/metadata/agent.py:203 msgid "" "The remote metadata server responded with Forbidden. This response " @@ -185,34 +190,34 @@ msgid "" "greater to 0" msgstr "" -#: neutron/api/extensions.py:535 +#: neutron/api/extensions.py:537 #, python-format msgid "Did not find expected name \"%(ext_name)s\" in %(file)s" msgstr "" -#: neutron/api/extensions.py:543 +#: neutron/api/extensions.py:545 #, python-format msgid "Extension file %(f)s wasn't loaded due to %(exception)s" msgstr "" -#: neutron/api/extensions.py:581 +#: neutron/api/extensions.py:583 #, python-format msgid "Extension %s not supported by any of loaded plugins" msgstr "" -#: neutron/api/extensions.py:592 +#: neutron/api/extensions.py:594 #, python-format msgid "Loaded plugins do not implement extension %s interface" msgstr "" -#: neutron/api/rpc/agentnotifiers/dhcp_rpc_agent_api.py:73 +#: neutron/api/rpc/agentnotifiers/dhcp_rpc_agent_api.py:81 #, python-format msgid "" "Unable to schedule network %s: no agents available; will retry on " "subsequent port and subnet creation events." msgstr "" -#: neutron/api/rpc/agentnotifiers/dhcp_rpc_agent_api.py:91 +#: neutron/api/rpc/agentnotifiers/dhcp_rpc_agent_api.py:99 #, python-format msgid "" "Only %(active)d of %(total)d DHCP agents associated with network " @@ -245,19 +250,19 @@ msgid "" "performance impact." msgstr "" -#: neutron/db/agents_db.py:201 +#: neutron/db/agents_db.py:202 #, python-format msgid "%(agent_type)s agent %(agent_id)s is not active" msgstr "" -#: neutron/db/agents_db.py:223 +#: neutron/db/agents_db.py:224 #, python-format msgid "" "Dictionary %(dict_name)s for agent %(agent_type)s on host %(host)s is " "invalid." msgstr "" -#: neutron/db/agents_db.py:289 +#: neutron/db/agents_db.py:290 #, python-format msgid "" "Agent healthcheck: found %(count)s dead agents out of %(total)s:\n" @@ -272,11 +277,11 @@ msgid "" "in case there was a clock adjustment." msgstr "" -#: neutron/db/agentschedulers_db.py:286 +#: neutron/db/agentschedulers_db.py:285 msgid "No DHCP agents available, skipping rescheduling" msgstr "" -#: neutron/db/agentschedulers_db.py:290 +#: neutron/db/agentschedulers_db.py:289 #, python-format msgid "" "Removing network %(network)s from agent %(agent)s because the agent did " @@ -288,21 +293,21 @@ msgstr "" msgid "Cannot schedule BgpSpeaker to DrAgent. Reason: No scheduler registered." msgstr "" -#: neutron/db/l3_agentschedulers_db.py:121 +#: neutron/db/l3_agentschedulers_db.py:128 #, python-format msgid "" "Rescheduling router %(router)s from agent %(agent)s because the agent did" " not report to the server in the last %(dead_time)s seconds." msgstr "" -#: neutron/db/l3_agentschedulers_db.py:316 +#: neutron/db/l3_agentschedulers_db.py:323 #, python-format msgid "" "Failed to notify L3 agent on host %(host)s about added router. Attempt " "%(attempt)d out of %(max_attempts)d" msgstr "" -#: neutron/db/l3_dvr_db.py:784 +#: neutron/db/l3_dvr_db.py:826 #, python-format msgid "Router %s was not found. Skipping agent notification." msgstr "" @@ -337,7 +342,7 @@ msgid "No plugin found for resource:%s. API calls may not be correctly dispatche msgstr "" #: neutron/pecan_wsgi/controllers/resource.py:74 -#: neutron/pecan_wsgi/controllers/root.py:96 +#: neutron/pecan_wsgi/controllers/root.py:98 #, python-format msgid "No controller found for: %s - returning response code 404" msgstr "" @@ -364,11 +369,11 @@ msgstr "" msgid "Failed to bind port %(port)s on host %(host)s at level %(lvl)s" msgstr "" -#: neutron/plugins/ml2/plugin.py:865 +#: neutron/plugins/ml2/plugin.py:862 msgid "A concurrent port creation has occurred" msgstr "" -#: neutron/plugins/ml2/plugin.py:1556 +#: neutron/plugins/ml2/plugin.py:1552 #, python-format msgid "Port %s not found during update" msgstr "" @@ -439,15 +444,15 @@ msgstr "" msgid "Invalid Segmentation ID: %s, will lead to incorrect vxlan device name" msgstr "" -#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:569 -#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:606 +#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:579 +#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:616 #, python-format msgid "" "Option \"%(option)s\" must be supported by command \"%(command)s\" to " "enable %(mode)s mode" msgstr "" -#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:600 +#: neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py:610 msgid "" "VXLAN muticast group(s) must be provided in vxlan_group option to enable " "VXLAN MCAST mode" @@ -458,12 +463,12 @@ msgstr "" msgid "Cannot find vf index for pci slot %s" msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/eswitch_manager.py:364 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/eswitch_manager.py:365 #, python-format msgid "device pci mismatch: %(device_mac)s - %(pci_slot)s" msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/eswitch_manager.py:388 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/eswitch_manager.py:389 #, python-format msgid "" "VF with PCI slot %(pci_slot)s is already assigned; skipping reset maximum" @@ -480,22 +485,22 @@ msgstr "" msgid "failed to parse vf link show line %(line)s: for %(device)s" msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:235 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:239 #, python-format msgid "Failed to set spoofcheck for device %s" msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:244 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:248 #, python-format msgid "Device %s does not support state change" msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:247 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:251 #, python-format msgid "Failed to set device %s state" msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:328 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:332 #, python-format msgid "port_id to device with MAC %s not found" msgstr "" @@ -520,42 +525,42 @@ msgid "" "or the gateway may have already been deleted" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:593 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:591 #, python-format msgid "Action %s not supported" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1371 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1373 #, python-format msgid "VIF port: %s has no ofport configured, and might not be able to transmit" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1496 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1498 #, python-format msgid "Device %s not defined on plugin or binding failed" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1652 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1654 #, python-format msgid "Invalid remote IP: %s" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1705 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1707 msgid "OVS is restarted. OVSNeutronAgent will reset bridges and recover ports." msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1708 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1710 msgid "" "OVS is dead. OVSNeutronAgent will keep running and checking OVS status " "periodically." msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1764 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1766 #, python-format msgid "Clearing cache of registered ports, retries to resync were > %s" msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1838 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:1840 #, python-format msgid "Device %(dev)s failed for %(times)s times and won't be retried anymore" msgstr "" @@ -595,16 +600,16 @@ msgstr "" msgid "No more DHCP agents" msgstr "" -#: neutron/scheduler/l3_agent_scheduler.py:148 +#: neutron/scheduler/l3_agent_scheduler.py:149 #, python-format msgid "No routers compatible with L3 agent configuration on host %s" msgstr "" -#: neutron/scheduler/l3_agent_scheduler.py:173 +#: neutron/scheduler/l3_agent_scheduler.py:174 msgid "No active L3 agents" msgstr "" -#: neutron/scheduler/l3_agent_scheduler.py:179 +#: neutron/scheduler/l3_agent_scheduler.py:180 #, python-format msgid "No L3 agents can host the router %s" msgstr "" diff --git a/neutron/locale/neutron.pot b/neutron/locale/neutron.pot index 6f143033f27..cd91269cac3 100644 --- a/neutron/locale/neutron.pot +++ b/neutron/locale/neutron.pot @@ -6,16 +6,16 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.1.dev29\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-04-11 06:27+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-19 06:52+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.3.2\n" +"Generated-By: Babel 2.2.0\n" #: neutron/manager.py:73 #, python-format @@ -193,7 +193,7 @@ msgstr "" msgid "Availability zone of this node" msgstr "" -#: neutron/agent/common/config.py:88 +#: neutron/agent/common/config.py:87 msgid "" "Name of bridge used for external network traffic. This should be set to " "an empty value for the Linux Bridge. When this parameter is set, each L3 " @@ -201,7 +201,7 @@ msgid "" "option is deprecated and will be removed in the M release." msgstr "" -#: neutron/agent/common/config.py:158 neutron/common/config.py:195 +#: neutron/agent/common/config.py:157 neutron/common/config.py:195 msgid "" "Where to store Neutron state files. This directory must be writable by " "the agent." @@ -324,7 +324,7 @@ msgstr "" msgid "Extensions list to use" msgstr "" -#: neutron/agent/l3/agent.py:302 +#: neutron/agent/l3/agent.py:308 msgid "" "The 'gateway_external_network_id' option must be configured for this " "agent as Neutron has more than one external network." @@ -1952,13 +1952,13 @@ msgstr "" msgid "Shared address scope can't be unshared" msgstr "" -#: neutron/db/agents_db.py:45 +#: neutron/db/agents_db.py:46 msgid "" "Seconds to regard the agent is down; should be at least twice " "report_interval, to be sure the agent is down for good." msgstr "" -#: neutron/db/agents_db.py:50 +#: neutron/db/agents_db.py:51 msgid "" "Representing the resource type whose load is being reported by the agent." " This can be \"networks\", \"subnets\" or \"ports\". When specified " @@ -1973,7 +1973,7 @@ msgid "" "Example: dhcp_load_type=networks" msgstr "" -#: neutron/db/agents_db.py:66 +#: neutron/db/agents_db.py:67 msgid "" "Agent starts with admin_state_up=False when enable_new_agents=False. In " "the case, user's resources will not be scheduled automatically to the " @@ -2468,7 +2468,7 @@ msgstr "" msgid "cannot perform %(event)s due to %(reason)s" msgstr "" -#: neutron/db/securitygroups_db.py:694 +#: neutron/db/securitygroups_db.py:716 msgid "Default security group" msgstr "" @@ -3991,7 +3991,7 @@ msgstr "" msgid "Device has no virtual functions" msgstr "" -#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:427 +#: neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py:430 #, python-format msgid "Device name %(dev_name)s is missing from physical_device_mappings" msgstr "" @@ -4071,7 +4071,7 @@ msgstr "" msgid "Parsing bridge_mappings failed: %s." msgstr "" -#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:2055 +#: neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py:2060 msgid "" "DVR deployments for VXLAN/GRE/Geneve underlays require L2-pop to be " "enabled, in both the Agent and Server side." @@ -4514,7 +4514,7 @@ msgstr "" msgid "A metering driver must be specified" msgstr "" -#: neutron/services/metering/drivers/iptables/iptables_driver.py:88 +#: neutron/services/metering/drivers/iptables/iptables_driver.py:89 msgid "An interface driver must be specified" msgstr "" @@ -4545,11 +4545,12 @@ msgstr "" msgid "Async process didn't respawn" msgstr "" -#: neutron/tests/functional/agent/linux/test_keepalived.py:61 +#: neutron/tests/functional/agent/linux/test_keepalived.py:62 +#: neutron/tests/functional/agent/linux/test_keepalived.py:97 msgid "Keepalived didn't spawn" msgstr "" -#: neutron/tests/functional/agent/linux/test_keepalived.py:72 +#: neutron/tests/functional/agent/linux/test_keepalived.py:73 msgid "Keepalived didn't respawn" msgstr "" diff --git a/neutron/locale/pt_BR/LC_MESSAGES/neutron.po b/neutron/locale/pt_BR/LC_MESSAGES/neutron.po index af6fa92bebd..52d80b7fdca 100644 --- a/neutron/locale/pt_BR/LC_MESSAGES/neutron.po +++ b/neutron/locale/pt_BR/LC_MESSAGES/neutron.po @@ -11,9 +11,9 @@ # Lucas Palm , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.1.dev29\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-04-10 14:30+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-18 20:06+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/neutron/locale/ru/LC_MESSAGES/neutron.po b/neutron/locale/ru/LC_MESSAGES/neutron.po index 1d181076122..c359b548aa9 100644 --- a/neutron/locale/ru/LC_MESSAGES/neutron.po +++ b/neutron/locale/ru/LC_MESSAGES/neutron.po @@ -9,9 +9,9 @@ # Lucas Palm , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.1.dev29\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-04-10 14:30+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-18 20:06+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/neutron/locale/tr_TR/LC_MESSAGES/neutron-log-error.po b/neutron/locale/tr_TR/LC_MESSAGES/neutron-log-error.po index 6dc97a0301c..c5f3133ccd4 100644 --- a/neutron/locale/tr_TR/LC_MESSAGES/neutron-log-error.po +++ b/neutron/locale/tr_TR/LC_MESSAGES/neutron-log-error.po @@ -7,11 +7,12 @@ # Alper Çiftçi , 2015 # Zana iLHAN , 2015 # OpenStack Infra , 2015. #zanata +# Andreas Jaeger , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0b4.dev134\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-12 03:37+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-18 20:06+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -583,6 +584,10 @@ msgstr "" msgid "OVS flows could not be applied on bridge %s" msgstr "OVS akışları %s köprüsüne uygulanamıyor." +#, python-format +msgid "Parsing bridge_mappings failed: %s." +msgstr "bridge_mappins ayrıştırma başarısız: %s." + #, python-format msgid "Parsing physical_interface_mappings failed: %s. Agent terminated!" msgstr "" @@ -627,6 +632,9 @@ msgid "" "version %s." msgstr "Yüklü dnsmasq sürümü çok eski. Lütfen en az %s sürümüne güncelleyin." +msgid "The resource could not be found." +msgstr "Kaynak bulunamadı." + msgid "" "The user that is executing neutron does not have permissions to read the " "namespaces. Enable the use_helper_for_ns_read configuration option." diff --git a/neutron/locale/tr_TR/LC_MESSAGES/neutron-log-info.po b/neutron/locale/tr_TR/LC_MESSAGES/neutron-log-info.po index 89c9ae2a76b..e10fcaec698 100644 --- a/neutron/locale/tr_TR/LC_MESSAGES/neutron-log-info.po +++ b/neutron/locale/tr_TR/LC_MESSAGES/neutron-log-info.po @@ -8,9 +8,9 @@ # OpenStack Infra , 2015. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0b4.dev134\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-12 03:37+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-18 20:06+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/neutron/locale/tr_TR/LC_MESSAGES/neutron-log-warning.po b/neutron/locale/tr_TR/LC_MESSAGES/neutron-log-warning.po index 11147a41f4b..6380cac8829 100644 --- a/neutron/locale/tr_TR/LC_MESSAGES/neutron-log-warning.po +++ b/neutron/locale/tr_TR/LC_MESSAGES/neutron-log-warning.po @@ -7,9 +7,9 @@ # OpenStack Infra , 2015. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.0.0b4.dev134\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-03-12 03:37+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-18 20:06+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/neutron/locale/tr_TR/LC_MESSAGES/neutron.po b/neutron/locale/tr_TR/LC_MESSAGES/neutron.po index 20771e5226e..202a5ece808 100644 --- a/neutron/locale/tr_TR/LC_MESSAGES/neutron.po +++ b/neutron/locale/tr_TR/LC_MESSAGES/neutron.po @@ -7,11 +7,12 @@ # Alper Çiftçi , 2015 # Andreas Jaeger , 2015. #zanata # OpenStack Infra , 2015. #zanata +# Andreas Jaeger , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.1.dev29\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-04-10 14:30+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-18 20:06+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -253,6 +254,9 @@ msgstr "Bu kaynağa erişime izin verilmiyor." msgid "Action to be executed when a child process dies" msgstr "Alt süreç öldüğünde çalıştırılacak eylem" +msgid "Address not present on interface" +msgstr "Adres arayüzde mevcut değil" + #, python-format msgid "Address scope %(address_scope_id)s could not be found" msgstr "Adres kapsamı %(address_scope_id)s bulunamadı" @@ -366,6 +370,10 @@ msgstr "Gövde geçersiz veri içeriyor" msgid "Bridge %(bridge)s does not exist." msgstr "Köprü %(bridge)s mevcut değil." +#, python-format +msgid "Bridge %s does not exist" +msgstr "Köprü %s mevcut değil" + msgid "Bulk operation not supported" msgstr "Toplu işlem desteklenmiyor" @@ -417,6 +425,9 @@ msgstr "%(col)s=%(match)s olan %(table)s bulunamadı" msgid "Cannot handle subnet of type %(subnet_type)s" msgstr "%(subnet_type)s türünde alt ağ işlenemiyor" +msgid "Cannot have multiple IPv4 subnets on router port" +msgstr "Yönlendirici bağlantı noktasında birden fazla IPv4 alt ağı olamaz" + #, python-format msgid "" "Cannot have multiple router ports with the same network id if both contain " @@ -777,6 +788,12 @@ msgstr "%s dns adresinin ayrıştırılmasında hata" msgid "Error while reading %s" msgstr "%s okunurken hata" +#, python-format +msgid "" +"Exceeded %s second limit waiting for address to leave the tentative state." +msgstr "" +"Adresin belirsiz durumdan çıkması için %s saniye bekleme sınırı aşıldı." + msgid "Existing prefixes must be a subset of the new prefixes" msgstr "Mevcut önekler yeni öneklerin alt kümesi olmalıdır" @@ -875,10 +892,17 @@ msgstr "Uid %s ayarlanamadı" msgid "Failed to set-up %(type)s tunnel port to %(ip)s" msgstr "%(ip)s'ye %(type)s tünel bağlantı noktası kurulumu başarısız" +msgid "Failure applying iptables rules" +msgstr "Iptables kuralları uygulanırken başarısız olundu" + #, python-format msgid "Failure waiting for address %(address)s to become ready: %(reason)s" msgstr "%(address)s adresinin hazır olmasını bekleme başarısız: %(reason)s" +#, python-format +msgid "Flavor %(flavor_id)s could not be found." +msgstr "%(flavor_id)s örnek türü bulunamadı." + #, python-format msgid "Floating IP %(floatingip_id)s could not be found" msgstr "Değişken IP %(floatingip_id)s bulunamadı" @@ -1057,6 +1081,10 @@ msgstr "" "Geçersiz kimlik doğrulama türü: %(auth_type)s, geçerli türler: " "%(valid_auth_types)s" +#, python-format +msgid "Invalid content type %(content_type)s." +msgstr "Geçersiz içerik türü %(content_type)s." + #, python-format msgid "Invalid data format for IP pool: '%s'" msgstr "IP havuzu: '%s' için geçersiz veri biçimi" @@ -1440,6 +1468,10 @@ msgstr "" msgid "OK" msgstr "Tamam" +#, python-format +msgid "OVSDB Error: %s" +msgstr "OVSDB Hatası: %s" + msgid "Only admin can view or configure quota" msgstr "Yalnızca yönetici kotaları görüntüleyebilir ya da yapılandırabilir" @@ -1499,6 +1531,10 @@ msgstr "Eklenti sağlayıcı özniteliklerini güncellemeyi desteklemiyor" msgid "Port %(id)s does not have fixed ip %(address)s" msgstr "%(id)s bağlantı noktası %(address)s sabit ip'sine sahip değil" +#, python-format +msgid "Port %(port)s does not exist on %(bridge)s!" +msgstr "Bağlantı noktası %(port)s %(bridge)s köprüsü üzerinde mevcut değil!" + #, python-format msgid "" "Port %(port_id)s is associated with a different tenant than Floating IP " @@ -1507,6 +1543,10 @@ msgstr "" "%(port_id)s bağlantı noktası %(floatingip_id)s değişken IP'sinden başka bir " "kiracı ile ilişkilendirilmiş bu yüzden bağlanamaz." +#, python-format +msgid "Port %s does not exist" +msgstr "Bağlantı noktası %s mevcut değil" + msgid "" "Port Security must be enabled in order to have allowed address pairs on a " "port." @@ -1994,6 +2034,9 @@ msgstr "" "desteğini etkinleştirir. Bu kip merkezi bir düğümde çalışan L3 ajanı için " "kullanılmalıdır (veya tek-istemcili kurulumlarda, örn. devstack)" +msgid "Timeout" +msgstr "Zaman aşımı" + msgid "" "True to delete all ports on all the OpenvSwitch bridges. False to delete " "ports created by Neutron on integration and external network bridges." diff --git a/neutron/locale/zh_CN/LC_MESSAGES/neutron.po b/neutron/locale/zh_CN/LC_MESSAGES/neutron.po index ed1e58affd1..0d349d4fa6d 100644 --- a/neutron/locale/zh_CN/LC_MESSAGES/neutron.po +++ b/neutron/locale/zh_CN/LC_MESSAGES/neutron.po @@ -18,9 +18,9 @@ # Lucas Palm , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.1.dev29\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-04-10 14:30+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-18 20:06+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/neutron/locale/zh_TW/LC_MESSAGES/neutron.po b/neutron/locale/zh_TW/LC_MESSAGES/neutron.po index 6510a984533..b8b600f3487 100644 --- a/neutron/locale/zh_TW/LC_MESSAGES/neutron.po +++ b/neutron/locale/zh_TW/LC_MESSAGES/neutron.po @@ -9,9 +9,9 @@ # Lucas Palm , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.1.dev29\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2016-04-10 14:30+0000\n" +"Project-Id-Version: neutron 8.0.1.dev68\n" +"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" +"POT-Creation-Date: 2016-04-18 20:06+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" From 7fcf0253246832300f13b0aa4cea397215700572 Mon Sep 17 00:00:00 2001 From: OpenStack Proposal Bot Date: Thu, 21 Apr 2016 07:05:16 +0000 Subject: [PATCH 50/51] Imported Translations from Zanata For more information about this automatic import see: https://wiki.openstack.org/wiki/Translations/Infrastructure Change-Id: I9e930750dde85a9beb0b6f85eeea8a0962d3e020 --- neutron/locale/ko_KR/LC_MESSAGES/neutron.po | 243 ++++++------ neutron/locale/zh_TW/LC_MESSAGES/neutron.po | 409 ++++++++++---------- 2 files changed, 322 insertions(+), 330 deletions(-) diff --git a/neutron/locale/ko_KR/LC_MESSAGES/neutron.po b/neutron/locale/ko_KR/LC_MESSAGES/neutron.po index 4f8b7489053..54ae7941f23 100644 --- a/neutron/locale/ko_KR/LC_MESSAGES/neutron.po +++ b/neutron/locale/ko_KR/LC_MESSAGES/neutron.po @@ -8,20 +8,16 @@ # Sungjin Kang , 2013 # Sungjin Kang , 2013 # Sungjin Kang , 2013 -# Lucas Palm , 2015. #zanata -# OpenStack Infra , 2015. #zanata -# Lucas Palm , 2016. #zanata -# SeYeon Lee , 2016. #zanata # Sungjin Kang , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.1.dev68\n" +"Project-Id-Version: neutron 8.0.1.dev84\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-04-18 20:06+0000\n" +"POT-Creation-Date: 2016-04-20 11:10+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-04-11 01:53+0000\n" +"PO-Revision-Date: 2016-04-19 11:58+0000\n" "Last-Translator: SeYeon Lee \n" "Language: ko-KR\n" "Plural-Forms: nplurals=1; plural=0;\n" @@ -211,7 +207,7 @@ msgstr "'%s' 공백 문자열이 허용되지 않음" #, python-format msgid "'%s' cannot be converted to boolean" -msgstr "'%s'은(는) 부울로 변환될 수 없음" +msgstr "'%s'은(는) boolean으로 변환될 수 없음" #, python-format msgid "'%s' cannot be converted to lowercase string" @@ -235,7 +231,7 @@ msgstr "'%s'이(가) FQDN이 아님" #, python-format msgid "'%s' is not a dictionary" -msgstr "'%s'이(가) 사전이 아님" +msgstr "'%s'이(가) dictianry가 아님" #, python-format msgid "'%s' is not a list" @@ -394,7 +390,7 @@ msgstr "주소 범위 %(address_scope_id)s을(를) 찾을 수 없음" msgid "" "Address to listen on for OpenFlow connections. Used only for 'native' driver." msgstr "" -"OpenFlow 연결을 위해 청취할 주소입니다. '네이티브' 드라이버에만 사용됩니다. " +"OpenFlow 연결을 위해 청취할 주소입니다. 'native' 드라이버에만 사용됩니다. " msgid "Adds external network attribute to network resource." msgstr "외부 네트워크 속성을 네트워크 자원에 추가합니다." @@ -519,8 +515,8 @@ msgid "" "neutron.ml2.extension_drivers namespace. For example: extension_drivers = " "port_security,qos" msgstr "" -"neutron.ml2.mechanism_drivers 네임스페이스로부터 로드할 확장 드라이버 엔드포" -"인트의 정렬된 목록입니다. 예: extension_drivers = port_security,qos" +"neutron.ml2.mechanism_drivers 네임스페이스로부터 로드할 확장 드라이버 " +"endpoint의 정렬된 목록입니다. 예: extension_drivers = port_security,qos" msgid "" "An ordered list of networking mechanism driver entrypoints to be loaded from " @@ -629,12 +625,12 @@ msgid "" "Bad prefix or mac format for generating IPv6 address by EUI-64: %(prefix)s, " "%(mac)s:" msgstr "" -"EUI-64에 의해 IPv6 주소를 생성하기 위한 접두부 또는 mac 형식이 잘못되었습니" +"EUI-64에 의해 IPv6 주소를 생성하기 위한 prefix 또는 mac 형식이 잘못되었습니" "다. %(prefix)s, %(mac)s:" #, python-format msgid "Bad prefix type for generate IPv6 address by EUI-64: %s" -msgstr "EUI-64에 의해 IPv6 주소를 생성하기 위한 접두부 유형이 잘못됨: %s" +msgstr "EUI-64에 의해 IPv6 주소를 생성하기 위한 prefix 유형이 잘못됨: %s" #, python-format msgid "Base MAC: %s" @@ -677,7 +673,7 @@ msgid "Bridge %s does not exist" msgstr "브릿지 %s이(가) 없음" msgid "Bulk operation not supported" -msgstr "벌크 오퍼레이션은 지원되지 않음" +msgstr "Bulk 오퍼레이션은 지원되지 않음" msgid "CIDR to monitor" msgstr "모니터할 CIDR" @@ -692,11 +688,11 @@ msgstr "%(resource_type)s에 대한 콜백에서 잘못된 자원 유형을 리 #, python-format msgid "Cannot add floating IP to port %s that has no fixed IPv4 addresses" -msgstr "고정 IPv4 주소가 없는 포트 %s에 부동 IP를 추가할 수 없음" +msgstr "고정 IPv4 주소가 없는 포트 %s에 floating IP를 추가할 수 없음" #, python-format msgid "Cannot add floating IP to port on subnet %s which has no gateway_ip" -msgstr "gateway_ip를 갖지 않는 %s 서브넷의 포트에 부동 IP를 추가할 수 없음" +msgstr "gateway_ip를 갖지 않는 %s 서브넷의 포트에 floating IP를 추가할 수 없음" #, python-format msgid "Cannot add multiple callbacks for %(resource_type)s" @@ -707,7 +703,7 @@ msgid "Cannot allocate IPv%(req_ver)s subnet from IPv%(pool_ver)s subnet pool" msgstr "IPv%(pool_ver)s 서브넷 풀에서 IPv%(req_ver)s 서브넷을 할당할 수 없음" msgid "Cannot allocate requested subnet from the available set of prefixes" -msgstr "사용 가능한 접두부 세트에서 요청한 서브넷을 할당할 수 없음" +msgstr "사용 가능한 prefix 세트에서 요청한 서브넷을 할당할 수 없음" #, python-format msgid "" @@ -715,9 +711,10 @@ msgid "" "%(port_id)s using fixed IP %(fixed_ip)s, as that fixed IP already has a " "floating IP on external network %(net_id)s." msgstr "" -"고정 IP는 외부 네트워크 %(net_id)s에서 부동 IP를 가지고 있기 때문에 고정 IP " -"%(fixed_ip)s을(를) 사용하여 부동 IP %(floating_ip_address)s(%(fip_id)s)을" -"(를) 포트 %(port_id)s과(와) 연관시킬 수 없습니다. " +"Fixed IP는 외부 네트워크 %(net_id)s에서 floating IP를 가지고 있기 때문에 고" +"정 IP %(fixed_ip)s을(를) 사용하여 floating IP " +"%(floating_ip_address)s(%(fip_id)s)을(를) 포트 %(port_id)s과(와) 연관시킬 수 " +"없습니다. " msgid "" "Cannot change HA attribute of active routers. Please set router " @@ -730,15 +727,16 @@ msgstr "" msgid "" "Cannot create floating IP and bind it to %s, since that is not an IPv4 " "address." -msgstr "IPv4 주소가 아니므로 부동 IP를 작성하여 %s에 바인드할 수 없습니다. " +msgstr "" +"IPv4 주소가 아니므로 floating IP를 작성하여 %s에 바인드할 수 없습니다. " #, python-format msgid "" "Cannot create floating IP and bind it to Port %s, since that port is owned " "by a different tenant." msgstr "" -"부동 IP를 작성하여 포트 %s에 바인드할 수 없습니다. 해당 포트를 다른 테넌트가 " -"소유하기 때문입니다. " +"Floating IP를 작성하여 포트 %s에 바인드할 수 없습니다. 해당 포트를 다른 " +"tenant가 소유하기 때문입니다. " msgid "Cannot create resource for another tenant" msgstr "다른 테넌트에 대한 자원을 작성할 수 없음" @@ -777,7 +775,7 @@ msgid "Cannot match priority on flow deletion or modification" msgstr "플로우 삭제나 수정시 우선순위와 일치할 수 없음" msgid "Cannot mix IPv4 and IPv6 prefixes in a subnet pool." -msgstr "서브넷 풀에서 IPv4 및 IPv6 접두부를 혼합하여 사용할 수 없습니다." +msgstr "서브넷 풀에서 IPv4 및 IPv6 prefix를 혼합하여 사용할 수 없습니다." msgid "Cannot specify both --service and --subproject." msgstr "--service와 --subproject를 모두 지정할 수 없습니다. " @@ -800,7 +798,7 @@ msgstr "" "admin_state_up을 False로 설정하십시오. " msgid "Certificate Authority public key (CA cert) file for ssl" -msgstr "ssl용 인증 기관 공개 키(CA cert) 파일 " +msgstr "SSL용 인증 기관 공개 키(CA cert) 파일 " #, python-format msgid "" @@ -808,7 +806,7 @@ msgid "" msgstr "변경하면 다음 자원에 대한 사용량이 0보다 작아짐: %(unders)s." msgid "Check ebtables installation" -msgstr "ebtables 설치 확인" +msgstr "Ebtables 설치 확인" msgid "Check for ARP header match support" msgstr "ARP 헤더 일치 지원 확인" @@ -829,22 +827,22 @@ msgid "Check for VF management support" msgstr "VF 관리 지원 확인" msgid "Check for iproute2 vxlan support" -msgstr "iproute2 vxlan 지원 확인" +msgstr "IProute2 vxlan 지원 확인" msgid "Check for nova notification support" -msgstr "nova 알림 지원 확인" +msgstr "Nova 알림 지원 확인" msgid "Check for patch port support" msgstr "패치 포트 지원 확인" msgid "Check ip6tables installation" -msgstr "ip6tables 설치 확인" +msgstr "IP6tables 설치 확인" msgid "Check ipset installation" -msgstr "ipset 설치 확인" +msgstr "IPSet 설치 확인" msgid "Check keepalived IPv6 support" -msgstr "keepalived IPv6 지원 확인" +msgstr "Keepalived IPv6 지원 확인" msgid "Check minimal dibbler version" msgstr "최소 dibbler 버전 확인" @@ -853,13 +851,13 @@ msgid "Check minimal dnsmasq version" msgstr "최소 dnsmasq 버전 확인" msgid "Check netns permission settings" -msgstr "netns 권한 설정 확인" +msgstr "NetNS 권한 설정 확인" msgid "Check ovs conntrack support" -msgstr "ovs conntrack 지원 확인" +msgstr "OVS conntrack 지원 확인" msgid "Check ovsdb native interface support" -msgstr "ovsdb 네이티브 인터페이스 지원 확인" +msgstr "Ovsdb 네이티브 인터페이스 지원 확인" #, python-format msgid "" @@ -940,21 +938,21 @@ msgid "" "Comma-separated list of : tuples enumerating ranges of GRE " "tunnel IDs that are available for tenant network allocation" msgstr "" -"테넌트 네트워크 할당에 사용 가능한 GRE 터널 ID의 범위를 열거한 :" +"Tenant 네트워크 할당에 사용 가능한 GRE 터널 ID의 범위를 열거한 :" " 튜플을 쉼표로 구분한 목록입니다." msgid "" "Comma-separated list of : tuples enumerating ranges of " "Geneve VNI IDs that are available for tenant network allocation" msgstr "" -"테넌트 네트워크 할당에 사용 가능한 Geneve VNI ID의 범위를 열거하는 :" +"Tenant 네트워크 할당에 사용 가능한 Geneve VNI ID의 범위를 열거하는 :" " 튜플의 쉼표로 구분된 목록입니다. " msgid "" "Comma-separated list of : tuples enumerating ranges of " "VXLAN VNI IDs that are available for tenant network allocation" msgstr "" -"테넌트 네트워크 할당에 사용 가능한 VXLAN VNI ID의 범위를 열거한 :" +"Tenant 네트워크 할당에 사용 가능한 VXLAN VNI ID의 범위를 열거한 :" " 튜플의 쉼표로 구분된 목록입니다. " msgid "" @@ -1104,12 +1102,12 @@ msgid "" "Default number of RBAC entries allowed per tenant. A negative value means " "unlimited." msgstr "" -"테넌트당 허용되는 기본 RBAC 항목 수입니다. 음수 값은 무제한을 의미합니다. " +"Tenant당 허용되는 기본 RBAC 항목 수입니다. 음수 값은 무제한을 의미합니다. " msgid "" "Default number of resource allowed per tenant. A negative value means " "unlimited." -msgstr "테넌트당 허용되는 기본 자원 수입니다. 음수 값은 무제한을 의미합니다." +msgstr "Tenant당 허용되는 기본 자원 수입니다. 음수 값은 무제한을 의미합니다." msgid "Default security group" msgstr "기본 보안 그룹" @@ -1164,10 +1162,10 @@ msgid "Deployment error: %(reason)s." msgstr "배포 오류: %(reason)s." msgid "Destroy IPsets even if there is an iptables reference." -msgstr "iptables 참조가 있는 경우에도 IPset를 영구 삭제하십시오. " +msgstr "IPtables 참조가 있는 경우에도 IPSet를 영구 삭제하십시오. " msgid "Destroy all IPsets." -msgstr "모든 IPset를 영구 삭제하십시오. " +msgstr "모든 IPSet를 영구 삭제하십시오. " #, python-format msgid "Device %(dev_name)s in mapping: %(mapping)s not unique" @@ -1470,7 +1468,7 @@ msgid "" "Exit code: %(returncode)d; Stdin: %(stdin)s; Stdout: %(stdout)s; Stderr: " "%(stderr)s" msgstr "" -"종료 코드: %(returncode)d; Stdin: %(stdin)s; Stdout: %(stdout)s; Stderr: " +"Exit code: %(returncode)d; Stdin: %(stdin)s; Stdout: %(stdout)s; Stderr: " "%(stderr)s" #, python-format @@ -1518,7 +1516,7 @@ msgid "" "IP." msgstr "" "서브넷 %(subnet_id)s에서 외부 네트워크 %(external_network_id)s에 도달할 수 없" -"습니다. 따라서 포트 %(port_id)s을(를) 부동 IP와 연관시킬 수 없습니다. " +"습니다. 따라서 포트 %(port_id)s을(를) floating IP와 연관시킬 수 없습니다. " #, python-format msgid "" @@ -1567,7 +1565,7 @@ msgid "" "Failed to associate address scope: subnetpools within an address scope must " "have unique prefixes." msgstr "" -"주소 범위를 연관시키는 데 실패: 주소 범위의 subnetpool에는 고유한 접두어가 있" +"주소 범위를 연관시키는 데 실패: 주소 범위의 subnetpool에는 고유한 prefix가 있" "어야 합니다." #, python-format @@ -1621,7 +1619,7 @@ msgid "Failed to set-up %(type)s tunnel port to %(ip)s" msgstr "%(type)s 터널 포트를 %(ip)s(으)로 설정하지 못함" msgid "Failure applying iptables rules" -msgstr "iptables 규칙 적용 실패" +msgstr "Iptables 규칙 적용 실패" #, python-format msgid "Failure waiting for address %(address)s to become ready: %(reason)s" @@ -1643,15 +1641,15 @@ msgstr "Flavor가 사용되지 않습니다." #, python-format msgid "Floating IP %(floatingip_id)s could not be found" -msgstr "%(floatingip_id)s 부동 IP를 찾을 수 없음" +msgstr "%(floatingip_id)s floating IP를 찾을 수 없음" #, python-format msgid "" "Floating IP %(floatingip_id)s is associated with non-IPv4 address " "%s(internal_ip)s and therefore cannot be bound." msgstr "" -"부동 IP %(floatingip_id)s이(가) 비IPv4 주소 %s(internal_ip)s과(와) 연관되어 " -"있으므로 바인드할 수 없습니다. " +"Floating IP %(floatingip_id)s이(가) 비IPv4 주소 %s(internal_ip)s과(와) 연관되" +"어 있으므로 바인드할 수 없습니다. " msgid "For TCP/UDP protocols, port_range_min must be <= port_range_max" msgstr "TCP/UDP 프로토콜의 경우 port_range_min은 port_range_max 이하여야 함" @@ -1681,8 +1679,9 @@ msgid "" "Gateway cannot be updated for router %(router_id)s, since a gateway to " "external network %(net_id)s is required by one or more floating IPs." msgstr "" -"외부 네트워크 %(net_id)s에 대한 게이트웨이가 하나 이상의 부동 IP에서 필요로 " -"하기 때문에 라우터 %(router_id)s에 대한 게이트웨이를 업데이트할 수 없습니다. " +"외부 네트워크 %(net_id)s에 대한 게이트웨이가 하나 이상의 floating IP에서 필요" +"로 하기 때문에 라우터 %(router_id)s에 대한 게이트웨이를 업데이트할 수 없습니" +"다. " #, python-format msgid "Gateway ip %(ip_address)s conflicts with allocation pool %(pool)s." @@ -1740,7 +1739,7 @@ msgstr "" "min)이 누락되었습니다." msgid "ID of network" -msgstr "네트워크의 ID" +msgstr "네트워크 ID" msgid "ID of network to probe" msgstr "프로브할 네트워크의 ID" @@ -1789,14 +1788,14 @@ msgstr "" msgid "IPtables conntrack zones exhausted, iptables rules cannot be applied." msgstr "" -"IPtables conntrack 구역이 소진되었습니다. iptables 규칙을 적용할 수 없습니" +"IPtables conntrack 구역이 소진되었습니다. IPtables 규칙을 적용할 수 없습니" "다. " msgid "IPv6 Address Mode must be SLAAC or Stateless for Prefix Delegation." -msgstr "IPv6 주소 모드는 접두부 위임에 대해 Stateless 또는 SLAAC여야 합니다. " +msgstr "IPv6 주소 모드는 prefix 위임에 대해 Stateless 또는 SLAAC여야 합니다. " msgid "IPv6 RA Mode must be SLAAC or Stateless for Prefix Delegation." -msgstr "IPv6 RA 모드는 접두부 위임에 대해 Stateless 또는 SLAAC여야 합니다. " +msgstr "IPv6 RA 모드는 prefix 위임에 대해 Stateless 또는 SLAAC여야 합니다. " #, python-format msgid "" @@ -1851,7 +1850,7 @@ msgid "" "Illegal prefix bounds: %(prefix_type)s=%(prefixlen)s, %(base_prefix_type)s=" "%(base_prefixlen)s." msgstr "" -"잘못된 접두부 바운드: %(prefix_type)s=%(prefixlen)s, %(base_prefix_type)s=" +"잘못된 prefix 바운드: %(prefix_type)s=%(prefixlen)s, %(base_prefix_type)s=" "%(base_prefixlen)s." #, python-format @@ -1878,7 +1877,7 @@ msgstr "잘못된 subnetpool 업데이트 : %(reason)s." #, python-format msgid "Illegal update to prefixes: %(msg)s." -msgstr "잘못된 접두부 업데이트: %(msg)s." +msgstr "잘못된 prefix 업데이트: %(msg)s." msgid "" "In some cases the Neutron router is not present to provide the metadata IP " @@ -1916,7 +1915,7 @@ msgstr "" #, python-format msgid "Insufficient prefix space to allocate subnet size /%s" -msgstr "접두부 공간이 부족하여 서브넷 크기 /%s을(를) 할당할 수 없음" +msgstr "Prefix 공간이 부족하여 서브넷 크기 /%s을(를) 할당할 수 없음" msgid "Insufficient rights for removing default security group." msgstr "기본 보안 그룹을 제거할 수 있는 권한이 없습니다." @@ -2109,7 +2108,7 @@ msgid "Keepalived didn't respawn" msgstr "유휴되면 다시 파생되지 않음" msgid "Keepalived didn't spawn" -msgstr "활성 유지(keepalive)가 파생되지 않음" +msgstr "Keepalive가 파생되지 않음" #, python-format msgid "" @@ -2143,8 +2142,8 @@ msgid "" "networks, as well as ranges of VLAN tags on each available for allocation to " "tenant networks." msgstr "" -"테넌트 네트워크에 대한 할당에 사용할 수 있는 각 VLAN 태그의 범위 및VLAN 제공" -"자와 테넌트 네트워크에 사용할 수 있는 실제 네트워크 이름을 지정하는 " +"Tenant 네트워크에 대한 할당에 사용할 수 있는 각 VLAN 태그의 범위 및VLAN 제공" +"자와 tenant 네트워크에 사용할 수 있는 실제 네트워크 이름을 지정하는 " ":: 또는 의 목록입니" "다." @@ -2171,7 +2170,7 @@ msgid "Local IP address of tunnel endpoint." msgstr "터널 엔드포인트의 로컬 IP 주소입니다." msgid "Location for Metadata Proxy UNIX domain socket." -msgstr "메타데이터 프록시 UNIX 도메인 소켓의 위치입니다." +msgstr "메타데이터 프록시 UNIX 도메인 소켓 위치입니다." msgid "Location of Metadata Proxy UNIX domain socket" msgstr "메타데이터 프록시 UNIX 도메인 소켓 위치" @@ -2362,11 +2361,11 @@ msgid "" "(24-bit) VNI, use a /8 such as 239.0.0.0/8. This setting must be the same on " "all the agents." msgstr "" -"vxlan 인터페이스의 멀티캐스트 그룹입니다. 그룹 주소의 범위는 CIDR 표기법을 사" +"Vxlan 인터페이스의 멀티캐스트 그룹입니다. 그룹 주소의 범위는 CIDR 표기법을 사" "용하여 지정할 수 있습니다. 범위를 지정하면 여러 다른 VNI에서 여러 다른 그룹 " -"주소를 사용할 수 있으므로, 터널 엔드포인트에 대한 의사 브로드캐스트 트래픽이 " -"감소하거나 제거됩니다. 가능한 각 (24비트) VNI의 고유 그룹을 유지하려면 /8을 " -"사용하십시오(예: 239.0.0.0/8). 이 설정은 모든 에이전트에서 같아야 합니다." +"주소를 사용할 수 있으므로, 터널 endpoint에 대한 의사 브로드캐스트 트래픽이 감" +"소하거나 제거됩니다. 가능한 각 (24비트) VNI의 고유 그룹을 유지하려면 /8을 사" +"용하십시오(예: 239.0.0.0/8). 이 설정은 모든 에이전트에서 같아야 합니다." #, python-format msgid "Multiple agents with agent_type=%(agent_type)s and host=%(host)s found" @@ -2446,7 +2445,7 @@ msgstr "" "기 전에 모든 Neutron 서버 인스턴스를 종료해야 합니다." msgid "Negative delta (downgrade) not supported" -msgstr "음수의 델타(다운그레이드)는 지원하지 않음" +msgstr "음수의 delta (downgrade)는 지원하지 않음" msgid "Negative relative revision (downgrade) not supported" msgstr "음수의 상대적 개정판(다운그레이드)은 지원하지 않음" @@ -2627,17 +2626,17 @@ msgstr "" msgid "" "Number of floating IPs allowed per tenant. A negative value means unlimited." -msgstr "테넌트당 허용된 부동 IP 수입니다. 음수 값은 무제한을 의미합니다." +msgstr "Tenant당 허용된 부동 IP 수입니다. 음수 값은 무제한을 의미합니다." msgid "" "Number of networks allowed per tenant. A negative value means unlimited." -msgstr "테넌트당 허용되는 네트워크 수입니다. 음수 값은 무제한을 의미합니다." +msgstr "Tenant당 허용되는 네트워크 수입니다. 음수 값은 무제한을 의미합니다." msgid "Number of ports allowed per tenant. A negative value means unlimited." -msgstr "테넌트당 허용되는 포트 수입니다. 음수 값은 무제한을 의미합니다." +msgstr "Tenant당 허용되는 포트 수입니다. 음수 값은 무제한을 의미합니다." msgid "Number of routers allowed per tenant. A negative value means unlimited." -msgstr "테넌트당 허용된 라우터 수입니다. 음수 값은 무제한을 의미합니다." +msgstr "Tenant당 허용된 라우터 수입니다. 음수 값은 무제한을 의미합니다." msgid "" "Number of seconds between sending events to nova if there are any events to " @@ -2672,7 +2671,7 @@ msgstr "" "지정됨)" msgid "Number of subnets allowed per tenant, A negative value means unlimited." -msgstr "테넌트당 허용되는 서브넷 수입니다. 음수 값은 무제한을 의미합니다." +msgstr "Tenant당 허용되는 서브넷 수입니다. 음수 값은 무제한을 의미합니다." msgid "" "Number of threads to use during sync process. Should not exceed connection " @@ -2740,7 +2739,7 @@ msgid "" "value 'local' is useful for single-box testing but provides no connectivity " "between hosts." msgstr "" -"테넌트 네트워크로 할당할 network_types의 정렬된 목록입니다. 기본값 'local'은 " +"Tenant 네트워크로 할당할 network_types의 정렬된 목록입니다. 기본값 'local'은 " "단일 상자 테스트에 유용하지만 호스트 간 연결을 제공하지 않습니다." msgid "Override the default dnsmasq settings with this file." @@ -2787,7 +2786,7 @@ msgid "Peer patch port in tunnel bridge for integration bridge." msgstr "통합 브릿지에 대한 터널 브릿지에 있는 피어 패치 포트입니다." msgid "Per-tenant subnet pool prefix quota exceeded." -msgstr "테넌트당 서브넷 풀 접두부 할당량이 초과되었습니다." +msgstr "Tenant당 서브넷 풀 Prefix 할당량이 초과되었습니다." msgid "Phase upgrade options do not accept revision specification" msgstr "단계 업그레이드 옵션이 개정 스펙을 승인하지 않음" @@ -2822,8 +2821,8 @@ msgid "" "Port %(port_id)s is associated with a different tenant than Floating IP " "%(floatingip_id)s and therefore cannot be bound." msgstr "" -"포트 %(port_id)s이(가) 부동 IP %(floatingip_id)s과(와) 다른 테넌트와 연관되" -"어 있어서 바운드할 수 없습니다. " +"포트 %(port_id)s이(가) Floating IP %(floatingip_id)s과(와) 다른 tenant와 연관" +"되어 있어서 바운드할 수 없습니다. " #, python-format msgid "Port %(port_id)s is not managed by this agent. " @@ -2838,8 +2837,8 @@ msgid "" "Port %s has multiple fixed IPv4 addresses. Must provide a specific IPv4 " "address when assigning a floating IP" msgstr "" -"포트 %s에 다중 고정 IPv4 주소가 있습니다. 부동 IP를 지정하는 경우에는 특정 " -"IPv4 주소를 제공해야 합니다. " +"포트 %s에 다중 fixed IPv4 주소가 있습니다. Floating IP를 지정하는 경우에는 특" +"정 IPv4 주소를 제공해야 합니다. " msgid "" "Port Security must be enabled in order to have allowed address pairs on a " @@ -2863,14 +2862,14 @@ msgstr "" msgid "" "Port to listen on for OpenFlow connections. Used only for 'native' driver." msgstr "" -"OpenFlow 연결을 위해 청취할 포트입니다. '네이티브' 드라이버에만 사용됩니다. " +"OpenFlow 연결을 위해 청취할 포트입니다. 'native' 드라이버에만 사용됩니다. " #, python-format msgid "Prefix '%(prefix)s' not supported in IPv%(version)s pool." -msgstr "IPv%(version)s 풀에서 접두부 '%(prefix)s'이(가) 지원되지 않습니다." +msgstr "IPv%(version)s 풀에서 prefix '%(prefix)s'이(가) 지원되지 않습니다." msgid "Prefix Delegation can only be used with IPv6 subnets." -msgstr "접두부 위임은 IPv6 서브넷에만 사용할 수 있습니다. " +msgstr "Prefix 위임은 IPv6 서브넷에만 사용할 수 있습니다. " msgid "Private key of client certificate." msgstr "클라이언트 인증서 개인 키입니다." @@ -3005,10 +3004,10 @@ msgstr "" "에이전트에서 로드를 보고하는 자원 유형을 나타냅니다. 이는 \"네트워크\", \"서" "브넷\" 또는 \"포트\"입니다. 이를 지정하는 경우 (기본값은 네트워크임) 서버는 " "network_scheduler_driver = neutron.scheduler.dhcp_agent_scheduler." -"WeightScheduler와의 조합에서 report_interval.dhcp_load_type을 사용할 수 있을 " -"때마다 에이전트 보고 상태에서 에이전트 구성 오브젝트의 일부로 보낸 특정 로드" -"를 추출하는데, 이는 이용 중인 자원 수입니다. network_scheduler_driver가 " -"WeightScheduler인 경우 dhcp_load_type을 구성하여 밸런스 조정 중인 자원에 대" +"WeightScheduler 와의 조합에서 report_interval.dhcp_load_type 을 사용할 수 있" +"을 때마다 에이전트 보고 상태에서 에이전트 구성 오브젝트의 일부로 보낸 특정 로" +"드를 추출하는데, 이는 이용 중인 자원 수입니다. network_scheduler_driver 가 " +"WeightScheduler 인 경우 dhcp_load_type을 구성하여 밸런스 조정 중인 자원에 대" "한 선택을 표시할 수 있습니다. 예: dhcp_load_type=networks" msgid "Request Failed: internal server error while processing your request." @@ -3121,8 +3120,8 @@ msgid "" "Router interface for subnet %(subnet_id)s on router %(router_id)s cannot be " "deleted, as it is required by one or more floating IPs." msgstr "" -"하나 이상의 부동 IP에서 필요로 하므로 %(router_id)s 라우터의 %(subnet_id)s 서" -"브넷에 대한 라우터 인터페이스를 삭제할 수 없습니다. " +"하나 이상의 floating IP에서 필요로 하므로 %(router_id)s 라우터의 " +"%(subnet_id)s 서브넷에 대한 라우터 인터페이스를 삭제할 수 없습니다. " #, python-format msgid "" @@ -3158,7 +3157,7 @@ msgid "Running %(cmd)s for %(project)s ..." msgstr "%(project)s에 대한 %(cmd)s 실행 중..." msgid "Running without keystone AuthN requires that tenant_id is specified" -msgstr "키스톤 AuthN 없이 실행하려면 테넌트 ID를 지정해야 합니다. " +msgstr "키스톤 AuthN 없이 실행하려면 tenant ID를 지정해야 합니다. " msgid "" "Seconds between nodes reporting state to server; should be less than " @@ -3308,10 +3307,10 @@ msgid "" "Specifying 'tenant_id' other than authenticated tenant in request requires " "admin privileges" msgstr "" -"요청에서 인증된 테넌트가 아닌 'tenant_id'를 지정하려면 admin 권한이 필요함" +"요청에서 인증된 tenant가 아닌 'tenant_id'를 지정하려면 admin 권한이 필요함" msgid "String prefix used to match IPset names." -msgstr "IPset 이름을 일치시키는 데 사용되는 문자열 접두부입니다. " +msgstr "IPSet 이름을 일치시키는 데 사용되는 문자열 prefix입니다. " #, python-format msgid "Sub-project %s not installed." @@ -3343,13 +3342,13 @@ msgstr "" "동일한 네트워크에서 호스트되는 서브넷을 동일한 서브넷 풀에서 할당해야 합니다." msgid "Suffix to append to all namespace names." -msgstr "모든 네임스페이스 이름에 추가될 접미어입니다." +msgstr "모든 네임스페이스 이름에 추가될 suffix입니다." msgid "" "System-wide flag to determine the type of router that tenants can create. " "Only admin can override." msgstr "" -"테넌트가 작성할 수 있는 라우터 유형을 판별하는 시스템 범위 플래그입니다. 관리" +"Tenant가 작성할 수 있는 라우터 유형을 판별하는 시스템 범위 플래그입니다. 관리" "자만 대체할 수 있습니다." msgid "TCP Port to listen for metadata server requests." @@ -3392,10 +3391,10 @@ msgid "Tenant name for connecting to designate in admin context" msgstr "관리 컨텍스트에서 지정하기 위해 연결할 테넌트 이름" msgid "Tenant network creation is not enabled." -msgstr "테넌트 네트워크 작성은 사용되지 않습니다. " +msgstr "Tenant 네트워크 작성은 사용되지 않습니다. " msgid "Tenant-id was missing from quota request." -msgstr "테넌트 ID가 할당량 요청에서 누락되었습니다. " +msgstr "Teanant ID가 할당량 요청에서 누락되었습니다. " msgid "" "The 'gateway_external_network_id' option must be configured for this agent " @@ -3469,9 +3468,9 @@ msgid "" "remain unchanged. If the 4th octet is not 00, it will also be used. The " "others will be randomly generated." msgstr "" -"VIF에기본 MAC 주소 Neutron을 사용합니다. 처음 세 개의 옥텟은 변경되지 않은 상" -"태로 남습니다. 네 번째 옥텟이 00이 아니면 이 옥텟도 사용됩니다. 다른 옥텟은 " -"임의로 생성됩니다." +"VIF에 기본 MAC 주소 Neutron을 사용합니다. 처음 세 개의 octet은 변경되지 않은 " +"상태로 남습니다. 네 번째 octet이 00이 아니면 이 octet도 사용됩니다. 다른 " +"octet은 임의로 생성됩니다." msgid "" "The base mac address used for unique DVR instances by Neutron. The first 3 " @@ -3482,10 +3481,10 @@ msgid "" "The default is 3 octet" msgstr "" "Neutron에 의해 고유 DVR 인스턴스에 사용되는 기본 mac 주소입니다. 처음 세 개 " -"옥텟은 변경되지 않고 남아 있습니다. 네 번째 옥텟이 00이 아니면 이 옥텟도 사용" -"됩니다. 다른 옥텟은 무작위로 생성됩니다. 테넌트 포트에 대해 할당된 MAC과의 혼" -"합을 방지하기 위해 'dvr_base_mac'은 'base_mac'과 달라야 *합니다*. 4 옥텟 예제" -"는 dvr_base_mac = fa:16:3f:4f:00:00입니다. 기본값은 3 옥텟입니다. " +"octet은 변경되지 않고 남아 있습니다. 네 번째 octet이 00이 아니면 이 octet도 " +"사용됩니다. 다른 octet은 무작위로 생성됩니다. Tenant 포트에 대해 할당된 MAC과" +"의 혼합을 방지하기 위해 'dvr_base_mac'은 'base_mac'과 달라야 *합니다*. 4 " +"octet 예제는 dvr_base_mac = fa:16:3f:4f:00:00입니다. 기본값은 3 octet입니다. " msgid "" "The connection string for the native OVSDB backend. Requires the native " @@ -3539,7 +3538,7 @@ msgid "" "The following device_id %(device_id)s is not owned by your tenant or matches " "another tenants router." msgstr "" -"device_id %(device_id)s이(가) 사용자 테넌트의 소유가 아니거나 다른 테넌트 라" +"device_id %(device_id)s이(가) 사용자 tenant의 소유가 아니거나 다른 tenant 라" "우터와 일치합니다." msgid "The host IP to bind to" @@ -3703,21 +3702,21 @@ msgid "" "Timeout in seconds to wait for a single OpenFlow request. Used only for " "'native' driver." msgstr "" -"단일 OpenFlow 요청을 기다리는 제한시간(초)입니다. '네이티브' 드라이버에만 사" -"용됩니다. " +"단일 OpenFlow 요청을 기다리는 제한시간(초)입니다. 'native' 드라이버에만 사용" +"됩니다. " msgid "" "Timeout in seconds to wait for the local switch connecting the controller. " "Used only for 'native' driver." msgstr "" -"제어기에 연결되는 로컬 스위치를 기다리는 제한시간(초)입니다. '네이티브' 드라" -"이버에만 사용됩니다. " +"제어기에 연결되는 로컬 스위치를 기다리는 제한시간(초)입니다. 'native' 드라이" +"버에만 사용됩니다. " msgid "" "Too long prefix provided. New name would exceed given length for an " "interface name." msgstr "" -"너무 긴 접두어가 제공되었습니다. 새 이름이 인터페이스 이름에 지정된 길이를 초" +"너무 긴 prefix가 지정되었습니다. 새 이름이 인터페이스 이름에 지정된 길이를 초" "과합니다." msgid "Too many availability_zone_hints specified" @@ -3758,16 +3757,16 @@ msgid "" "Unable to allocate subnet with prefix length %(prefixlen)s, maximum allowed " "prefix is %(max_prefixlen)s." msgstr "" -"접두부 길이가 %(prefixlen)s인 서브넷을 할당할 수 없습니다. 허용되는 최대 접두" -"부 길이는 %(max_prefixlen)s입니다. " +"Prefix 길이가 %(prefixlen)s인 서브넷을 할당할 수 없습니다. 허용되는 최대 " +"Prefix 길이는 %(max_prefixlen)s입니다. " #, python-format msgid "" "Unable to allocate subnet with prefix length %(prefixlen)s, minimum allowed " "prefix is %(min_prefixlen)s." msgstr "" -"접두부 길이가 %(prefixlen)s인 서브넷을 할당할 수 없습니다. 허용되는 최소 접두" -"부 길이는 %(min_prefixlen)s입니다. " +"Prefix 길이가 %(prefixlen)s인 서브넷을 할당할 수 없습니다. 허용되는 최소 " +"prefix 길이는 %(min_prefixlen)s입니다. " #, python-format msgid "Unable to calculate %(address_type)s address because of:%(reason)s" @@ -3851,7 +3850,7 @@ msgid "Unable to find resource name in %s" msgstr "%s에서 자원 이름을 찾을 수 없음" msgid "Unable to generate IP address by EUI64 for IPv4 prefix" -msgstr "IPv4 접두부에 대해 EUI64에 의해 IP 주소를 생성할 수 없습니다." +msgstr "IPv4 prefix에 대해 EUI64에 의해 IP 주소를 생성할 수 없습니다." #, python-format msgid "Unable to generate unique DVR mac for host %(host)s." @@ -3873,15 +3872,15 @@ msgid "Unable to provide external connectivity" msgstr "외부 연결을 제공할 수 없음" msgid "Unable to provide tenant private network" -msgstr "테넌트 개인 네트워크를 제공할 수 없음" +msgstr "Tenant 개인 네트워크를 제공할 수 없음" #, python-format msgid "" "Unable to reconfigure sharing settings for network %(network)s. Multiple " "tenants are using it." msgstr "" -"%(network)s 네트워크에 대한 공유 설정을 재구성할 수 없습니다. 여러 개의 테넌" -"트가 이를 사용 중입니다. " +"%(network)s 네트워크에 대한 공유 설정을 재구성할 수 없습니다. 여러 개의 " +"tenant가 이를 사용 중입니다. " #, python-format msgid "Unable to update address scope %(address_scope_id)s : %(reason)s" @@ -3985,7 +3984,7 @@ msgid "Use broadcast in DHCP replies." msgstr "DHCP 복제본에서 브로드캐스팅을 사용하십시오." msgid "Use either --delta or relative revision, not both" -msgstr "--델타 또는 상대적 개정판 중 하나 사용" +msgstr "--delta 또는 relative revision 중 하나 사용" msgid "" "Use ipset to speed-up the iptables based security groups. Enabling ipset " @@ -4048,12 +4047,12 @@ msgid "" "Validation of dictionary's keys failed. Expected keys: %(expected_keys)s " "Provided keys: %(provided_keys)s" msgstr "" -"사전의 키를 유효성 검증하지 못했습니다. 예상 키: %(expected_keys)s 제공된 " -"키: %(provided_keys)s" +"Dictionary 키에대한 유효성 검증을 하지 못했습니다. 만료된 키: " +"%(expected_keys)s 제공된 키: %(provided_keys)s" #, python-format msgid "Validator '%s' does not exist." -msgstr "유효성 검증기 '%s'이(가) 없습니다. " +msgstr "Validator '%s'이(가) 없습니다. " #, python-format msgid "Value %(value)s in mapping: '%(mapping)s' not unique" @@ -4216,7 +4215,7 @@ msgstr "%(dev_name)s 디바이스에 대한 ip 명령 실패: %(reason)s" #, python-format msgid "ip command failed: %(reason)s" -msgstr "ip 명령 실패: %(reason)s" +msgstr "IP 명령 실패: %(reason)s" #, python-format msgid "ip link capability %(capability)s is not supported" @@ -4253,7 +4252,7 @@ msgstr "" "이어야 합니다." msgid "mac address update" -msgstr "mac 주소 업데이트" +msgstr "MAC 주소 업데이트" #, python-format msgid "" @@ -4332,7 +4331,7 @@ msgid "subnetpool_id and use_default_subnetpool cannot both be specified" msgstr "subnetpool_id 및 use_default_subnetpool을 모두 지정할 수 없음" msgid "the nexthop is not connected with router" -msgstr "nexthop이 라우터와 연결되지 않음" +msgstr "Nexthop이 라우터와 연결되지 않음" msgid "the nexthop is used by router" msgstr "라우터가 nexthop을 사용함" diff --git a/neutron/locale/zh_TW/LC_MESSAGES/neutron.po b/neutron/locale/zh_TW/LC_MESSAGES/neutron.po index b8b600f3487..ee1099e9a34 100644 --- a/neutron/locale/zh_TW/LC_MESSAGES/neutron.po +++ b/neutron/locale/zh_TW/LC_MESSAGES/neutron.po @@ -3,19 +3,16 @@ # This file is distributed under the same license as the neutron project. # # Translators: -# Lucas Palm , 2015. #zanata -# OpenStack Infra , 2015. #zanata # Jennifer , 2016. #zanata -# Lucas Palm , 2016. #zanata msgid "" msgstr "" -"Project-Id-Version: neutron 8.0.1.dev68\n" +"Project-Id-Version: neutron 8.0.1.dev84\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-04-18 20:06+0000\n" +"POT-Creation-Date: 2016-04-20 11:10+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-03-18 12:34+0000\n" +"PO-Revision-Date: 2016-04-20 09:07+0000\n" "Last-Translator: Jennifer \n" "Language: zh-TW\n" "Plural-Forms: nplurals=1; plural=0;\n" @@ -70,8 +67,8 @@ msgid "" "%(method)s called with network settings %(current)s (original settings " "%(original)s) and network segments %(segments)s" msgstr "" -"已使用網路設定 %(current)s(原始設定%(original)s)及網路區段 %(segments)s 來" -"呼叫了 %(method)s" +"已使用網路設定 %(current)s(原始設定 %(original)s)及網路區段 %(segments)s 呼" +"叫了 %(method)s" #, python-format msgid "" @@ -93,8 +90,7 @@ msgstr "" msgid "" "%(method)s called with subnet settings %(current)s (original settings " "%(original)s)" -msgstr "" -"已使用子網路設定 %(current)s(原始設定%(original)s)來呼叫了 %(method)s" +msgstr "已使用子網路設定 %(current)s(原始設定 %(original)s)呼叫了 %(method)s" #, python-format msgid "%(method)s failed." @@ -122,7 +118,7 @@ msgstr "對於 sort_key 來說,%s 是無效的屬性" #, python-format msgid "%s is not a valid VLAN tag" -msgstr "%s 不是有效的 VLAN 標籤" +msgstr "%s 不是有效的 VLAN 標記" #, python-format msgid "%s must be specified" @@ -162,7 +158,7 @@ msgstr "" #, python-format msgid "'%(data)s' exceeds maximum length of %(max_len)s" -msgstr "'%(data)s' 超出 %(max_len)s 的長度上限" +msgstr "'%(data)s' 超出長度上限 %(max_len)s" #, python-format msgid "'%(data)s' is not an accepted IP address, '%(ip)s' is recommended" @@ -190,7 +186,7 @@ msgstr "'%(data)s' 不是有效的 PQDN 或 FQDN。原因:%(reason)s" #, python-format msgid "'%(host)s' is not a valid nameserver. %(msg)s" -msgstr "'%(host)s' 不是有效的命名伺服器。%(msg)s" +msgstr "'%(host)s' 不是有效的名稱伺服器。%(msg)s" #, python-format msgid "'%s' Blank strings are not permitted" @@ -202,7 +198,7 @@ msgstr "無法將 '%s' 轉換為布林值" #, python-format msgid "'%s' cannot be converted to lowercase string" -msgstr "'%s' 無法轉換為小寫字串" +msgstr "無法將 '%s' 轉換為小寫字串" #, python-format msgid "'%s' contains whitespace" @@ -334,7 +330,7 @@ msgid "" "mapping is :. This mapping allows specifying a physical " "network MTU value that differs from the default segment_mtu value." msgstr "" -"實體網路與 MTU 值的對映清單。對映格式為:。此對映容許指定不" +"實體網路與 MTU 值的對映清單。對映格式為 :。此對映容許指定不" "同於預設 segment_mtu 值的實體網路 MTU 值。" msgid "A metering driver must be specified" @@ -350,7 +346,7 @@ msgid "Aborting periodic_sync_routers_task due to an error." msgstr "由於發生錯誤,正在中斷 periodic_sync_routers_task。" msgid "Access to this resource was denied." -msgstr "拒絕存取此資源。" +msgstr "已拒絕存取此資源。" msgid "Action to be executed when a child process dies" msgstr "子程序當掉時要執行的動作" @@ -386,11 +382,11 @@ msgstr "找不到代理程式 %(id)s" #, python-format msgid "Agent %(id)s is not a L3 Agent or has been disabled" -msgstr "代理程式 %(id)s 不是 L3 代理程式或者已停用" +msgstr "代理程式 %(id)s 不是 L3 代理程式,或者已停用" #, python-format msgid "Agent %(id)s is not a valid DHCP Agent or has been disabled" -msgstr "代理程式 %(id)s 不是有效的 DHCP 代理程式或者已停用" +msgstr "代理程式 %(id)s 不是有效的 DHCP 代理程式,或者已停用" msgid "Agent has just been revived" msgstr "代理程式剛剛恢復" @@ -417,7 +413,7 @@ msgid "Allow auto scheduling networks to DHCP agent." msgstr "容許自動將網路排程到 DHCP 代理程式。" msgid "Allow auto scheduling of routers to L3 agent." -msgstr "容許自動將路由器排定到 L3 代理程式。" +msgstr "容許自動將路由器排程到 L3 代理程式。" msgid "" "Allow overlapping IP support in Neutron. Attention: the following parameter " @@ -495,8 +491,8 @@ msgid "" "neutron.ml2.extension_drivers namespace. For example: extension_drivers = " "port_security,qos" msgstr "" -"要從 neutron.ml2.extension_drivers 名稱空間載入之延伸驅動程式進入點的有序清" -"單。例如:extension_drivers = port_security,qos" +"要從 neutron.ml2.extension_drivers 名稱空間載入的延伸驅動程式進入點有序清單。" +"例如:extension_drivers = port_security,qos" msgid "" "An ordered list of networking mechanism driver entrypoints to be loaded from " @@ -526,14 +522,14 @@ msgid "Authorization URL for connecting to designate in admin context" msgstr "用於連接以在管理環境定義中指定的授權 URL" msgid "Automatically remove networks from offline DHCP agents." -msgstr "從離線 DHCP 代理程式自動移除網路。" +msgstr "從離線 DHCP 代理程式中自動移除網路。" msgid "" "Automatically reschedule routers from offline L3 agents to online L3 agents." -msgstr "自動將路由器從離線 L3 代理程式重新排定至線上 L3代理程式。" +msgstr "自動將路由器從離線 L3 代理程式重新排程至線上 L3 代理程式。" msgid "Availability zone of this node" -msgstr "此節點的可用性區域。" +msgstr "此節點的可用性區域" #, python-format msgid "AvailabilityZone %(availability_zone)s could not be found." @@ -556,7 +552,7 @@ msgid "" "at %(peer_ip)s, it cannot peer with BGP Peer %(bgp_peer_id)s." msgstr "" "BGP 喇叭 %(bgp_speaker_id)s 已經配置成與 %(peer_ip)s 處的 BGP 對等項對等,它" -"無法與 %(bgp_peer_id)s 處的 BGP 對等項對等。" +"無法與 BGP 對等項 %(bgp_peer_id)s 對等。" #, python-format msgid "" @@ -633,7 +629,7 @@ msgid "Body contains invalid data" msgstr "內文包含無效資料" msgid "Both network_id and router_id are None. One must be provided." -msgstr "network_id 及 router_id 皆為 None。必須提供其中一個。" +msgstr "network_id 及 router_id 均為 None。必須提供其中一個。" #, python-format msgid "Bridge %(bridge)s does not exist." @@ -674,7 +670,7 @@ msgid "Cannot allocate IPv%(req_ver)s subnet from IPv%(pool_ver)s subnet pool" msgstr "無法從 IPv%(pool_ver)s 子網路儲存區配置 IPv%(req_ver)s 子網路" msgid "Cannot allocate requested subnet from the available set of prefixes" -msgstr "無法配置可用字首集中的所要求子網路" +msgstr "無法從可用的字首集配置所要求的子網路" #, python-format msgid "" @@ -683,21 +679,21 @@ msgid "" "floating IP on external network %(net_id)s." msgstr "" "無法使浮動 IP %(floating_ip_address)s (%(fip_id)s) 與使用固定 IP " -"%(fixed_ip)s 的埠 %(port_id)s 產生關聯,因為該固定 IP 在外部網路 %(net_id)s " +"%(fixed_ip)s 的埠 %(port_id)s 建立關聯,因為該固定 IP 在外部網路 %(net_id)s " "上已經有浮動 IP。" msgid "" "Cannot change HA attribute of active routers. Please set router " "admin_state_up to False prior to upgrade." msgstr "" -"無法變更作用中路由器的 HA 屬性。請先將路由器 admin_state_up 設為 False,然後" -"再升級。" +"無法變更作用中路由器的 HA 屬性。請先將路由器的 admin_state_up 設為 False,然" +"後再升級。" #, python-format msgid "" "Cannot create floating IP and bind it to %s, since that is not an IPv4 " "address." -msgstr "無法建立浮動 IP 並將其連結至 %s,因為這不是一個 IPv4位址。" +msgstr "無法建立浮動 IP 並將其連結至 %s,因為這不是一個 IPv4 位址。" #, python-format msgid "" @@ -706,7 +702,7 @@ msgid "" msgstr "無法建立浮動 IP 並將其連結至埠 %s,因為該埠是由其他承租人擁有。" msgid "Cannot create resource for another tenant" -msgstr "無法給另一個 Tenant 建立資源" +msgstr "無法給另一個承租人建立資源" msgid "Cannot disable enable_dhcp with ipv6 attributes set" msgstr "在設定了 ipv6 屬性的情況下,無法停用 enable_dhcp" @@ -758,8 +754,8 @@ msgid "" "Cannot upgrade active router to distributed. Please set router " "admin_state_up to False prior to upgrade." msgstr "" -"無法將作用中路由器升級至分散式。請先將路由器admin_state_up 設定為 False,再升" -"級。" +"無法將作用中路由器升級至分散式。請先將路由器的 admin_state_up 設定為 False," +"然後再升級。" msgid "Certificate Authority public key (CA cert) file for ssl" msgstr "用於 SSL 的「憑證管理中心」公開金鑰(CA 憑證)檔案" @@ -812,10 +808,10 @@ msgid "Check minimal dibbler version" msgstr "檢查 dibbler 版本下限" msgid "Check minimal dnsmasq version" -msgstr "檢查最低 dnsmasq 版本" +msgstr "檢查 dnsmasq 版本下限" msgid "Check netns permission settings" -msgstr "檢查 netns 權限設定" +msgstr "檢查 netns 許可權設定" msgid "Check ovs conntrack support" msgstr "檢查 ovs conntrack 支援" @@ -878,9 +874,9 @@ msgid "" "physical networks listed in network_vlan_ranges on the server should have " "mappings to appropriate interfaces on each agent." msgstr "" -"實體網路名稱與要用於 VLAN 網路之 SR-IOV 實體功能的代理程式節點專用實體網路裝" -"置介面的: 值組對映清單(使用逗點區隔)。列" -"在伺服器上network_vlan_ranges 中的所有實體網路都應該具有與每個代理程式上適當" +"實體網路名稱與要用於 VLAN 網路之 SR-IOV 實體函數的代理程式節點專用實體網路裝" +"置介面的 : 值組對映清單(使用逗點區隔)。列" +"在伺服器上 network_vlan_ranges 中的所有實體網路都應該具有與每個代理程式上適當" "介面的對映。" msgid "" @@ -890,9 +886,9 @@ msgid "" "listed in network_vlan_ranges on the server should have mappings to " "appropriate interfaces on each agent." msgstr "" -"實體網路名稱與要用於平面網路及 VLAN 網路之代理程式節點專用實體網路介面的" +"實體網路名稱與要用於平面網路及 VLAN 網路之代理程式節點專用實體網路介面的 " ": 值組對映清單(使用逗點區隔)。列在伺" -"服器上network_vlan_ranges 中的所有實體網路都應該具有與每個代理程式上適當介面" +"服器上 network_vlan_ranges 中的所有實體網路都應該具有與每個代理程式上適當介面" "的對映。" msgid "" @@ -952,7 +948,7 @@ msgstr "嘗試 %(time)d 秒後仍無法連結至 %(host)s:%(port)s" #, python-format msgid "Could not connect to %s" -msgstr "無法連接 %s" +msgstr "無法連接至 %s" msgid "Could not deserialize data" msgstr "無法解除序列化資料" @@ -1016,8 +1012,8 @@ msgstr "" "要用於自動子網路 CIDR 配置的預設 IPv4 子網路儲存區。依 UUID 指定要使用的儲存" "區,以便於在沒有子網路儲存區 ID 情況下呼叫建立子網路。如果未設定,則將不使用" "儲存區,除非明確地將儲存區傳遞至子網路建立作業。如果不使用儲存區,則必須傳遞 " -"CIDR 以建立子網路,並且將不從任何儲存區中配置該子網路;會將其視為租戶專用位址" -"空間的一部分。這個選項已遭到淘汰,以在 N 版本中予以移除。" +"CIDR 以建立子網路,並且將不從任何儲存區中配置該子網路;會將其視為承租人專用位" +"址空間的一部分。這個選項已遭到淘汰,以在 N 版本中予以移除。" msgid "" "Default IPv6 subnet pool to be used for automatic subnet CIDR allocation. " @@ -1045,14 +1041,14 @@ msgid "" "config option." msgstr "" "在未指定提供者屬性時,外部網路的預設網路類型。依預設,它是「無」,這表示如果" -"在建立外部網路時未指定提供者屬性,則它們將相同的類型作為承租人網路。" +"在建立外部網路時未指定提供者屬性,則它們將具有與承租人網路相同的類型。" "external_network_type 配置選項所接受的值視 type_drivers 配置選項中配置的網路" "類型值而定。" msgid "" "Default number of RBAC entries allowed per tenant. A negative value means " "unlimited." -msgstr "每個承租人所容許的 RBAC 項目數目。負數值表示無限制。" +msgstr "每個承租人所容許的預設 RBAC 項目數目。負數值表示無限制。" msgid "" "Default number of resource allowed per tenant. A negative value means " @@ -1075,20 +1071,20 @@ msgid "" msgstr "" "可用性區域提示的預設值。當資源 availability_zone_hints 為空時,可用性區域知道" "排程器使用此項。可以透過逗點區隔的字串來指定多個可用性區域。此值可以是空的。" -"在這種情況下,即使資源 availability_zone_hints 為空,也會在排程資源時將可用性" -"區域視為高可用性。" +"在這種情況下,即使資源的 availability_zone_hints 為空,也會在排程資源時將可用" +"性區域視為高可用性。" msgid "" "Define the default value of enable_snat if not provided in " "external_gateway_info." msgstr "" -"定義 enable_snat 的預設值(如果未在external_gateway_info 中提供的話)。" +"定義 enable_snat 的預設值(如果未在 external_gateway_info 中提供的話)。" msgid "" "Defines providers for advanced services using the format: :" ":[:default]" msgstr "" -"使用下列格式,給進階服務定義提供者:::[:default]" +"使用下列格式,為進階服務定義提供者:::[:default]" msgid "" "Delay within which agent is expected to update existing ports whent it " @@ -1174,8 +1170,8 @@ msgid "" "defined in the neutron.agent.linux.pd_drivers namespace. See setup.cfg for " "entry points included with the neutron source." msgstr "" -"用於 IPv6 字首委派的驅動程式。這需要是 neutron.agent.linux.pd_drivers 中定義" -"的一個進入點。請參閱 setup.cfg,以取得Neutron 來源隨附的進入點。" +"用於 IPv6 字首委派的驅動程式。這需要是 neutron.agent.linux.pd_drivers 名稱空" +"間中定義的一個進入點。如需 Neutron 來源隨附的進入點,請參閱 setup.cfg。" msgid "Driver used for scheduling BGP speakers to BGP DrAgent" msgstr "用於將 BGP 喇叭排程至 BGP DrAgent 的驅動程式" @@ -1228,13 +1224,13 @@ msgid "" "ERROR: Unable to find configuration file via the default search paths (~/." "neutron/, ~/, /etc/neutron/, /etc/) and the '--config-file' option!" msgstr "" -"錯誤:無法透過預設搜尋路徑(~/.neutron/、~/、/etc/neutron/及 /etc/)與 '--" -"config-file' 選項來找到配置檔!" +"錯誤:透過預設搜尋路徑(~/.neutron/、~/、/etc/neutron/ 及 /etc/)與 '--" +"config-file' 選項找不到配置檔!" msgid "" "Either one of parameter network_id or router_id must be passed to _get_ports " "method." -msgstr "必須將 network_id 或 router_id 中的一個參數傳遞至_get_ports 方法。" +msgstr "必須將 network_id 或 router_id 中的一個參數傳遞至 _get_ports 方法。" msgid "Either subnet_id or port_id must be specified" msgstr "必須指定 subnet_id 或 port_id" @@ -1258,8 +1254,8 @@ msgid "" "Enable VXLAN on the agent. Can be enabled when agent is managed by ml2 " "plugin using linuxbridge mechanism driver" msgstr "" -"在代理程式上啟用 VXLAN。代理程式是由 ML2 外掛程式(使用 LinuxBridge 機制驅動" -"程式)管理時,可以啟用 VXLAN" +"在代理程式上啟用 VXLAN。當代理程式是由 ML2 外掛程式(使用 LinuxBridge 機制驅" +"動程式)管理時,可以啟用 VXLAN" msgid "" "Enable local ARP responder if it is supported. Requires OVS 2.1 and ML2 " @@ -1268,8 +1264,8 @@ msgid "" "into the overlay." msgstr "" "如果支援本端 ARP 回應者,請將其啟用。需要 OVS 2.1 及 ML2 l2population 驅動程" -"式。容許交換器(當支援套版時)在本端對 ARP 要求做出回應,但不執行高成本的 " -"ARP 播送至套版。" +"式。容許交換器(當支援套版時)在本端對 ARP 要求做出回應,但不執行指向套版的高" +"成本 ARP 廣播。" msgid "" "Enable local ARP responder which provides local responses instead of " @@ -1288,8 +1284,8 @@ msgid "" msgstr "" "對 admin_state_up 為 False 的代理程式啟用服務。如果此選項為 False,則當代理程" "式的 admin_state_up 變為 False 時,將停用其上的服務。無論此選項為何,都不會選" -"取 admin_state_up 為 False的代理程式以進行自動排程。但如果此選項為 True,則可" -"以使用此類代理程式的手動排程。" +"取 admin_state_up 為 False 的代理程式以進行自動排程。但如果此選項為 True,則" +"可以使用此類代理程式的手動排程。" msgid "" "Enable suppression of ARP responses that don't match an IP address that " @@ -1319,7 +1315,7 @@ msgid "" msgstr "" "按 meta 資料 Proxy 啟用/停用日誌監看。當不容許 metadata_proxy_user/group 讀" "取/寫入其日誌檔時,應該停用日誌監看,且如果已對 meta 資料 Proxy 日誌檔啟用 " -"logrotate,則必須使用copytruncate logrotate 選項。選項預設值是從" +"logrotate,則必須使用 copytruncate logrotate 選項。選項預設值是從 " "metadata_proxy_user 推斷得出的:如果 metadata_proxy_user 為代理程式有效使用" "者 ID/名稱,則已啟用日誌監看。" @@ -1342,7 +1338,7 @@ msgid "" "resolv' option from the dnsmasq process arguments. Adding custom DNS " "resolvers to the 'dnsmasq_dns_servers' option disables this feature." msgstr "" -"容許 dnsmasq 服務透過執行 DHCP 代理程式的主機上的 DNS 解析器,為實例提供名稱" +"容許 dnsmasq 服務透過執行 DHCP 代理程式之主機上的 DNS 解析器,為實例提供名稱" "解析。從 dnsmasq 程序引數中有效地移除 '--no-resolv' 選項。將自訂 DNS 解析器新" "增至 'dnsmasq_dns_servers' 選項會停用此功能。" @@ -1364,8 +1360,8 @@ msgid "" "Newton release, at which point the gateway will not be forced on to subnet." msgstr "" "請確保所配置的閘道位於子網路上。若為 IPv6,僅當閘道不是鏈結本端位址時,才進行" -"驗證。已淘汰,即將在 Newton 版本中予以移除,閘道在該發行版中將不強制在子網路" -"上予以啟用。" +"驗證。已遭到淘汰,即將在 Newton 版本中予以移除,閘道在該發行版中將不強制在子" +"網路上予以啟用。" #, python-format msgid "Error %(reason)s while attempting the operation." @@ -1444,14 +1440,14 @@ msgid "" "%(subnet_id)s. Therefore, cannot associate Port %(port_id)s with a Floating " "IP." msgstr "" -"無法從子網路 %(subnet_id)s 抵達外部網路 %(external_network_id)s。因此,無法使" -"埠 %(port_id)s 與浮動 IP 產生關聯。" +"無法從子網路 %(subnet_id)s 呼叫到外部網路 %(external_network_id)s。因此,無法" +"使埠 %(port_id)s 與浮動 IP 建立關聯。" #, python-format msgid "" "External network %(net_id)s cannot be updated to be made non-external, since " "it has existing gateway ports" -msgstr "無法將外部網路 %(net_id)s 更新成非外部網路,因為它具有現存的閘道埠" +msgstr "無法將外部網路 %(net_id)s 更新成非外部網路,因為它具有現有的閘道埠" #, python-format msgid "ExtraDhcpOpt %(id)s could not be found" @@ -1464,7 +1460,7 @@ msgstr "FWaaS 外掛程式已在伺服器端進行配置,但在 L3 代理程 #, python-format msgid "Failed rescheduling router %(router_id)s: no eligible l3 agent found." -msgstr "無法重新排定路由器 %(router_id)s:找不到適用的 L3 代理程式。" +msgstr "無法重新排程路由器 %(router_id)s:找不到適用的 L3 代理程式。" #, python-format msgid "Failed scheduling router %(router_id)s to the L3 Agent %(agent_id)s." @@ -1475,8 +1471,8 @@ msgid "" "Failed to allocate a VRID in the network %(network_id)s for the router " "%(router_id)s after %(max_tries)s tries." msgstr "" -"在嘗試 %(max_tries)s 次之後,無法為路由器 %(router_id)s配置網路 " -"%(network_id)s 中的 VRID。" +"在嘗試 %(max_tries)s 次之後,無法在路由器 %(router_id)s 的網路 " +"%(network_id)s 中配置 VRID。" #, python-format msgid "Failed to allocate subnet: %(reason)s." @@ -1496,8 +1492,7 @@ msgid "" "Failed to create a duplicate %(object_type)s: for attribute(s) " "%(attributes)s with value(s) %(values)s" msgstr "" -"針對下列屬性,無法建立複製的 %(object_type)s:%(attributes)s(值為 " -"%(values)s)" +"針對屬性 %(attributes)s(值為 %(values)s),無法建立重複的 %(object_type)s" #, python-format msgid "" @@ -1546,7 +1541,7 @@ msgid "Failure waiting for address %(address)s to become ready: %(reason)s" msgstr "等待位址 %(address)s 變成備妥時失敗:%(reason)s" msgid "Flat provider networks are disabled" -msgstr "已停用平面提供程序網路" +msgstr "已停用平面提供者網路" #, python-format msgid "Flavor %(flavor_id)s could not be found." @@ -1572,14 +1567,14 @@ msgstr "" "其連結。" msgid "For TCP/UDP protocols, port_range_min must be <= port_range_max" -msgstr "對於 TCP/UDP 通訊協定,port_range_min 必須 <= port_range_max" +msgstr "對於 TCP/UDP 通訊協定,port_range_min 必須小於或等於 port_range_max" #, python-format msgid "For class %(object_type)s missing primary keys: %(missing_keys)s" msgstr "針對類別 %(object_type)s,遺漏了主要索引鍵:%(missing_keys)s" msgid "Force ip_lib calls to use the root helper" -msgstr "強制 ip_lib 呼叫使用根說明程式" +msgstr "強制讓 ip_lib 呼叫使用根說明程式" #, python-format msgid "Found duplicate extension: %(alias)s." @@ -1589,8 +1584,7 @@ msgstr "發現重複延伸:%(alias)s。" msgid "" "Found overlapping allocation pools: %(pool_1)s %(pool_2)s for subnet " "%(subnet_cidr)s." -msgstr "" -"發現以下子網路的配置儲存區 %(pool_1)s %(pool_2)s重疊:%(subnet_cidr)s。" +msgstr "發現子網路 %(subnet_cidr)s 的配置儲存區 %(pool_1)s %(pool_2)s 重疊。" msgid "Gateway IP version inconsistent with allocation pool version" msgstr "閘道 IP 版本與配置儲存區版本不一致" @@ -1616,9 +1610,9 @@ msgid "" "ETH + IP + UDP + GENEVE header sizes. The default size for this field is 50, " "which is the size of the Geneve header without any additional option headers." msgstr "" -"Geneve 封裝標頭大小是動態的,此值用於計算驅動程式的 MTU 上限。這是其他 ETH 的" -"大小 + IP + UDP + GENEVE 標頭大小的總和。此欄位的預設大小是 50,這是 Geneve " -"標頭(不含任何其他選項標頭)的大小。" +"Geneve 封裝標頭大小是動態的,此值用於計算驅動程式的 MTU 上限。這是外部 ETH + " +"IP + UDP + GENEVE 標頭大小的大小總和。此欄位的預設大小是 50,這是 Geneve 標頭" +"(不含任何其他選項標頭)的大小。" msgid "Group (gid or name) running metadata proxy after its initialization" msgstr "在 meta 資料 Proxy 起始設定之後執行該 Proxy 的群組(GID 或名稱)" @@ -1627,7 +1621,7 @@ msgid "" "Group (gid or name) running metadata proxy after its initialization (if " "empty: agent effective group)." msgstr "" -"在 meta 資料 Proxy 起始設定之後執行該 Proxy 的群組(GID 或名稱)(如果為空:" +"在 meta 資料 Proxy 起始設定之後執行該 Proxy 的群組(GID 或名稱)(如果為空," "則為代理程式有效群組)。" msgid "Group (gid or name) running this process after its initialization" @@ -1653,7 +1647,7 @@ msgid "" "ICMP code (port-range-max) %(value)s is provided but ICMP type (port-range-" "min) is missing." msgstr "" -"提供了 ICMP 代碼 (port-range-max) %(value)s,但遺漏了 ICMP 類型(port-range-" +"提供了 ICMP 代碼 (port-range-max) %(value)s,但遺漏了 ICMP 類型 (port-range-" "min)。" msgid "ID of network" @@ -1732,7 +1726,7 @@ msgid "" "IPv6 subnet %s configured to receive RAs from an external router cannot be " "added to Neutron Router." msgstr "" -"無法將配置為從外部路由器接收 RA 的 IPv6 子網路 %s 新增至 Neutron 路由器。" +"無法將已配置成從外部路由器接收 RA 的 IPv6 子網路 %s 新增至 Neutron 路由器。" msgid "" "If True, advertise network MTU values if core plugin calculates them. MTU is " @@ -1811,7 +1805,7 @@ msgid "" msgstr "" "指示此 L3 代理程式還應該處理尚未配置外部網路閘道的路由器。針對 Neutron 部署中" "的單個代理程式,這個選項只應該為 True;如果所有路由器都必須具有外部網路閘道," -"則針對所有路由器,這個選項應該為 False。" +"則針對所有路由器,這個選項可能為 False。" #, python-format msgid "Instance of class %(module)s.%(class)s must contain _cache attribute" @@ -1951,7 +1945,7 @@ msgstr "無效的 PCI 插槽 %(pci_slot)s" #, python-format msgid "Invalid provider format. Last part should be 'default' or empty: %s" -msgstr "無效的提供者格式。最後一個部分應該是 'default' 或空白:%s" +msgstr "無效的提供者格式。最後一部分應該是 'default' 或空白:%s" #, python-format msgid "Invalid resource type %(resource_type)s" @@ -1972,7 +1966,7 @@ msgstr "服務類型 %(service_type)s 無效。" msgid "" "Invalid value for ICMP %(field)s (%(attr)s) %(value)s. It must be 0 to 255." msgstr "" -"ICMP %(field)s (%(attr)s) 的值 %(value)s 無效。該值必須在 0 到255 之間。" +"ICMP %(field)s (%(attr)s) 的值 %(value)s 無效。該值必須在 0 到 255 之間。" #, python-format msgid "Invalid value for port %(port)s" @@ -1996,8 +1990,8 @@ msgid "" "Keep in track in the database of current resourcequota usage. Plugins which " "do not leverage the neutron database should set this flag to False" msgstr "" -"保持追蹤資料庫中的現行 resourcequota 使用情形。不利用Neutron 資料庫的外掛程式" -"應該將此旗標設定為 False" +"保持追蹤資料庫中的現行 resourcequota 使用情形。不利用 Neutron 資料庫的外掛程" +"式應該將此旗標設定為 False" msgid "Keepalived didn't respawn" msgstr "Keepalived 未再次大量產生" @@ -2038,21 +2032,21 @@ msgid "" msgstr "" ":: 的清單,指定可" "用於 VLAN 提供者及承租人網路的 physical_network 名稱,以及在每個可用於配置給" -"承租人網路的 physical_network 上指定 VLAN標籤範圍。" +"承租人網路的 physical_network 上指定 VLAN 標記範圍。" msgid "" "List of network type driver entrypoints to be loaded from the neutron.ml2." "type_drivers namespace." msgstr "" -"要從 neutron.ml2.type_drivers 名稱空間中載入的網路類型驅動程式進入點清單。" +"要從 neutron.ml2.type_drivers 名稱空間載入的網路類型驅動程式進入點清單。" msgid "" "List of physical_network names with which flat networks can be created. Use " "default '*' to allow flat networks with arbitrary physical_network names. " "Use an empty list to disable flat networks." msgstr "" -"可用來建立平面網路的 physical_network 名稱清單。使用預設值 '*' 可容許含有任" -"意 physical_network 名稱的平面網路。使用空白清單可停用平面網路。" +"可用來建立平面網路的 physical_network 名稱清單。使用預設值 '*' 可容許使用含有" +"任意 physical_network 名稱的平面網路。使用空白清單可停用平面網路。" msgid "Local IP address of the VXLAN endpoints." msgstr "VXLAN 端點的本端 IP 位址。" @@ -2061,7 +2055,7 @@ msgid "Local IP address of tunnel endpoint." msgstr "通道端點的本端 IP 位址。" msgid "Location for Metadata Proxy UNIX domain socket." -msgstr "meta 資料 Proxy UNIX 網域 Socket 的位置" +msgstr "meta 資料 Proxy UNIX 網域 Socket 的位置。" msgid "Location of Metadata Proxy UNIX domain socket" msgstr "meta 資料 Proxy UNIX 網域 Socket 的位置" @@ -2177,10 +2171,10 @@ msgid "" "proxy socket mode to 0o666, to use otherwise." msgstr "" "meta 資料 Proxy UNIX 網域 Socket 模式,容許下列四個值:'deduce':來自 " -"metadata_proxy_user/group 值的 deduce 模式;'user':將 meta 資料 ProxySocket " -"模式設定為 0o644,以在 metadata_proxy_user 是代理程式有效使用者或 root 使用者" -"時使用;'group':將 meta 資料 Proxy Socket 模式設定為 0o664,以在 " -"metadata_proxy_group 是有效群組或 root 使用者時使用;'all':將 meta 資料" +"metadata_proxy_user/group 值的 deduce 模式;'user':將 meta 資料 Proxy " +"Socket 模式設定為 0o644,以在 metadata_proxy_user 是代理程式有效使用者或 " +"root 使用者時使用;'group':將 meta 資料 Proxy Socket 模式設定為 0o664,以在 " +"metadata_proxy_group 是有效群組或 root 使用者時使用;'all':將 meta 資料 " "Proxy Socket 模式設定為 0o666,以在其他情況下使用。" msgid "Metering driver" @@ -2263,11 +2257,11 @@ msgstr "服務 %s 的多個預設提供者" #, python-format msgid "Multiple plugins for service %s were configured" -msgstr "已給服務 %s 配置多個外掛程式" +msgstr "已為服務 %s 配置多個外掛程式" #, python-format msgid "Multiple providers specified for service %s" -msgstr "給服務 %s 指定了多個提供者" +msgstr "為服務 %s 指定了多個提供者" msgid "Multiple tenant_ids in bulk security group rule create not allowed" msgstr "不容許主體安全群組規則建立作業中存在多個 tenant_id" @@ -2302,8 +2296,8 @@ msgid "" "deprecated and will be removed in the M release." msgstr "" "用於外部網路資料流量的橋接器名稱。針對 Linux 橋接器,應該將此參數設為空值。設" -"定此參數時,每一個 L3 代理程式都可與不超過 1 個外部網路建立關聯。這個選項已淘" -"汰,並且將在 M 發行版中予以移除。" +"定此參數時,每一個 L3 代理程式都可與不超過 1 個外部網路建立關聯。這個選項已遭" +"到淘汰,並且將在 M 發行版中予以移除。" msgid "" "Name of nova region to use. Useful if keystone manages more than one region." @@ -2313,7 +2307,7 @@ msgid "Name of the FWaaS Driver" msgstr "FWaaS 驅動程式的名稱" msgid "Namespace of the router" -msgstr "路由器名稱空間" +msgstr "路由器的名稱空間" msgid "Native pagination depend on native sorting" msgstr "原生分頁相依於原生排序" @@ -2331,7 +2325,7 @@ msgid "Negative delta (downgrade) not supported" msgstr "不支援負數差異(降級)" msgid "Negative relative revision (downgrade) not supported" -msgstr "不支援負面的相對修訂(降級)" +msgstr "不支援負數相對修訂(降級)" #, python-format msgid "" @@ -2372,7 +2366,7 @@ msgstr "" "為 %(size)s 的網路。" msgid "Network that will have instance metadata proxied." -msgstr "其實例 meta 資料將被代理的網路。" +msgstr "將對其實例 meta 資料執行 Proxy 動作的網路。" #, python-format msgid "Network type value '%s' not supported" @@ -2390,8 +2384,8 @@ msgid "" "reference implementation of Neutron IPAM driver, use 'internal'." msgstr "" "要使用的 Neutron IPAM(IP 位址管理)驅動程式。如果未設定 ipam_driver(預設行" -"為),則將不使用任何 I者這PAM 驅動程式。如果要使用 Neutron IPAM 驅動程式的參" -"照實作,請使用「內部」。" +"為),則將不使用任何 PAM 驅動程式。如果要使用 Neutron IPAM 驅動程式的參照實" +"作,請使用「內部」。" msgid "Neutron Service Type Management" msgstr "Neutron 服務類型管理" @@ -2439,7 +2433,7 @@ msgstr "沒有擱置中的離線移轉。" #, python-format msgid "No providers specified for '%s' service, exiting" -msgstr "未給 '%s' 服務指定提供者,正在結束" +msgstr "未對 '%s' 服務指定提供者,正在結束" #, python-format msgid "No shared key in %s fields" @@ -2459,8 +2453,8 @@ msgid "" "Not enough l3 agents available to ensure HA. Minimum required " "%(min_agents)s, available %(num_agents)s." msgstr "" -"沒有足夠的 L3 代理程式可用,無法確保 HA。所需的數目下限為%(min_agents)s,可用" -"數目為 %(num_agents)s。" +"沒有足夠的 L3 代理程式可用,無法確保 HA。所需的數目下限為 %(min_agents)s,可" +"用數目為 %(num_agents)s。" msgid "" "Number of DHCP agents scheduled to host a tenant network. If this number is " @@ -2471,10 +2465,10 @@ msgstr "" "給定的承租人網路指派多個 DHCP 代理程式,為 DHCP 服務提供高可用性。" msgid "Number of RPC worker processes dedicated to state reports queue" -msgstr "專用於說明報告佇列的 RPC 工作者處理程序數目" +msgstr "專用於說明報告佇列的 RPC 工作程式程序數目" msgid "Number of RPC worker processes for service" -msgstr "服務的 RPC 工作者處理程序數目" +msgstr "服務的 RPC 工作程式程序數目" msgid "Number of backlog requests to configure the metadata server socket with" msgstr "要配置給 meta 資料伺服器 Socket 的待辦事項要求數目" @@ -2534,13 +2528,13 @@ msgid "" "Number of separate API worker processes for service. If not specified, the " "default is equal to the number of CPUs available for best performance." msgstr "" -"適用於服務的獨立 API 工作者處理程序數目。如果未指定,則預設值為可用於最佳效能" -"的 CPU 數目。" +"服務的獨立 API 工作程式程序數目。如果未指定,則預設值為可用於最佳效能的 CPU " +"數目。" msgid "" "Number of separate worker processes for metadata server (defaults to half of " "the number of CPUs)" -msgstr "meta 資料伺服器的獨立工作者處理程序數目(預設為CPU 數目的一半)" +msgstr "meta 資料伺服器的獨立工作程式程序數目(預設為 CPU 數目的一半)" msgid "Number of subnets allowed per tenant, A negative value means unlimited." msgstr "每個承租人所容許的子網路數目。負數值表示無限制。" @@ -2608,7 +2602,7 @@ msgid "" "value 'local' is useful for single-box testing but provides no connectivity " "between hosts." msgstr "" -"要配置作為租戶網路的 network_type 有序清單。預設值 'local' 對單框測試很有用," +"要配置為承租人網路的 network_type 有序清單。預設值 'local' 對單框測試很有用," "但卻不提供主機之間的連線功能。" msgid "Override the default dnsmasq settings with this file." @@ -2630,7 +2624,7 @@ msgstr "參數 %(param)s 必須是 %(param_type)s 類型。" #, python-format msgid "Parsing bridge_mappings failed: %s." -msgstr "剖析 bridge_mappings 時失敗:%s。" +msgstr "剖析 bridge_mappings 失敗:%s。" msgid "Parsing supported pci_vendor_devs failed" msgstr "剖析受支援的 pci_vendor_devs 失敗" @@ -2655,7 +2649,7 @@ msgid "Peer patch port in tunnel bridge for integration bridge." msgstr "通道橋接器中用於整合橋接器的同層級修補程式埠。" msgid "Per-tenant subnet pool prefix quota exceeded." -msgstr "已超出每個租戶的子網路儲存區字首配額。" +msgstr "已超出每個承租人的子網路儲存區字首配額。" msgid "Phase upgrade options do not accept revision specification" msgstr "階段升級選項不接受修訂規格" @@ -2690,8 +2684,8 @@ msgid "" "Port %(port_id)s is associated with a different tenant than Floating IP " "%(floatingip_id)s and therefore cannot be bound." msgstr "" -"埠 %(port_id)s 已與浮動 IP %(floatingip_id)s 之外的 Tenant 產生關聯,因此無法" -"連結。" +"埠 %(port_id)s 已與浮動 IP %(floatingip_id)s 之外的承租人建立關聯,因此無法連" +"結。" #, python-format msgid "Port %(port_id)s is not managed by this agent. " @@ -2715,7 +2709,7 @@ msgstr "必須啟用埠安全,才能在埠上使用位址配對。" msgid "" "Port has security group associated. Cannot disable port security or ip " "address until security group is removed" -msgstr "埠已與安全群組產生關聯。無法停用埠安全或 IP 位址,除非將安全群組移除" +msgstr "埠已與安全群組建立關聯。無法停用埠安全或 IP 位址,除非將安全群組移除" msgid "" "Port security must be enabled and port must have an IP address in order to " @@ -2797,7 +2791,7 @@ msgid "" "Range of seconds to randomly delay when starting the periodic task scheduler " "to reduce stampeding. (Disable by setting to 0)" msgstr "" -"啟動定期作業排定器以減少大混亂的隨機延遲秒數範圍。(如果要停用,則設為 0)" +"啟動定期作業排程器以減少大混亂時的隨機延遲秒數範圍。(如果要停用,請設為 0)" msgid "Ranges must be in the same IP version" msgstr "範圍必須位於相同的 IP 版本中" @@ -2851,13 +2845,13 @@ msgid "" "WeightScheduler, dhcp_load_type can be configured to represent the choice " "for the resource being balanced. Example: dhcp_load_type=networks" msgstr "" -"代表將由代理程式報告其負載的資源類型。它可以為「網路」、「子網路」或「埠」。" -"指定時(預設值為網路),伺服器將從代理程式報告狀態(為所耗用的資源數目)擷取" -"作為其代理程式配置物件一部分傳送的特定負載,擷取間隔為 report_interval." -"dhcp_load_type 可以與network_scheduler_driver = neutron.scheduler." -"dhcp_agent_scheduler.WeightScheduler 組合使用。當 network_scheduler_driver " -"為 WeightScheduler 時,可以將 dhcp_load_type配置為代表您選擇要進行平衡的資" -"源。範例:dhcp_load_type=網路" +"代表將由代理程式報告其負載的資源類型。它可以為 \"networks\"、\"subnets\" 或 " +"\"ports\"。指定時(預設值為 networks),伺服器將從代理程式報告狀態(為所耗用" +"的資源數目)擷取作為其代理程式配置物件一部分進行傳送的特定負載,擷取間隔為每" +"一個 report_interval。dhcp_load_type 可以與 network_scheduler_driver = " +"neutron.scheduler.dhcp_agent_scheduler.WeightScheduler 組合使用。當 " +"network_scheduler_driver 為 WeightScheduler 時,可以將 dhcp_load_type 配置為" +"代表您選擇要進行平衡的資源。範例:dhcp_load_type=networks" msgid "Request Failed: internal server error while processing your request." msgstr "要求失敗:處理要求時發生內部伺服器錯誤。" @@ -2867,14 +2861,15 @@ msgid "" "Request contains duplicate address pair: mac_address %(mac_address)s " "ip_address %(ip_address)s." msgstr "" -"要求包含重複的位址配對:mac_address %(mac_address)sip_address " +"要求包含重複的位址配對:mac_address %(mac_address)s ip_address " "%(ip_address)s。" #, python-format msgid "" "Requested subnet with cidr: %(cidr)s for network: %(network_id)s overlaps " "with another subnet" -msgstr "所要求的網路 %(network_id)s 子網路 (CIDR %(cidr)s) 與另一個子網路重疊" +msgstr "" +"所要求的網路 %(network_id)s 子網路(CIDR 為 %(cidr)s)與另一個子網路重疊" msgid "" "Reset flow table on start. Setting this to True will cause brief traffic " @@ -2896,7 +2891,7 @@ msgid "" "'%(provider)s' for service type '%(service_type)s'" msgstr "" "資源 '%(resource_id)s' 已與服務類型 '%(service_type)s' 的提供者 " -"'%(provider)s' 產生關聯" +"'%(provider)s' 建立關聯" msgid "Resource body required" msgstr "需要資源主體" @@ -2924,7 +2919,7 @@ msgid "Root helper daemon application to use when possible." msgstr "可能時要使用的根說明程式常駐程式應用程式。" msgid "Root permissions are required to drop privileges." -msgstr "需要 root 權限才能捨棄專用權。" +msgstr "需要 root 權限才能刪除專用權。" #, python-format msgid "Route %(cidr)s not advertised for BGP Speaker %(speaker_as)d." @@ -2956,14 +2951,14 @@ msgstr "路由器 '%(router_id)s' 與此代理程式不相容。" #, python-format msgid "Router already has a port on subnet %s" -msgstr "路由器在子網路 %s 上已經有埠" +msgstr "路由器在子網路 %s 上已經具有埠" #, python-format msgid "" "Router interface for subnet %(subnet_id)s on router %(router_id)s cannot be " "deleted, as it is required by one or more floating IPs." msgstr "" -"路由器 %(router_id)s 上子網路 %(subnet_id)s 的路由器介面無法刪除,因為一個以" +"無法刪除路由器 %(router_id)s 上子網路 %(subnet_id)s 的路由器介面,因為一個以" "上的浮動 IP 需要該介面。" #, python-format @@ -2971,14 +2966,14 @@ msgid "" "Router interface for subnet %(subnet_id)s on router %(router_id)s cannot be " "deleted, as it is required by one or more routes." msgstr "" -"路由器 %(router_id)s 上子網路 %(subnet_id)s 的路由器介面無法刪除,因為一個以" +"無法刪除路由器 %(router_id)s 上子網路 %(subnet_id)s 的路由器介面,因為一個以" "上的路徑需要該介面。" msgid "Router port must have at least one fixed IP" msgstr "路由器埠必須具有至少一個固定 IP" msgid "Router that will have connected instances' metadata proxied." -msgstr "其已連接的實例 meta 資料將被代理的路由器。" +msgstr "將對其已連接的實例 meta 資料執行 Proxy 動作的路由器。" #, python-format msgid "" @@ -3000,13 +2995,13 @@ msgid "Running %(cmd)s for %(project)s ..." msgstr "正在對 %(project)s 執行 %(cmd)s..." msgid "Running without keystone AuthN requires that tenant_id is specified" -msgstr "在沒有 Keystone AuthN 的情況下執行需要指定 tenant_id" +msgstr "在沒有 Keystone AuthN 的情況下執行時,需要指定 tenant_id" msgid "" "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." msgstr "" -"兩個節點將狀態報告給伺服器的間隔秒數;應該小於 agent_down_time;如果是 " +"節點將狀態報告給伺服器的間隔秒數;應該小於 agent_down_time;如果是 " "agent_down_time 的一半或者小於 agent_down_time,則最佳。" msgid "Seconds between running periodic tasks" @@ -3016,8 +3011,8 @@ msgid "" "Seconds to regard the agent is down; should be at least twice " "report_interval, to be sure the agent is down for good." msgstr "" -"將代理程式視為已關閉的秒數;應該至少是report_interval 的兩倍,以確保代理程式" -"已永久關閉。" +"將代理程式視為已關閉的秒數;應該至少是 report_interval 的兩倍,以確保代理程式" +"已完全關閉。" #, python-format msgid "Security Group %(id)s %(reason)s." @@ -3064,11 +3059,11 @@ msgid "" "Send notification to nova when port data (fixed_ips/floatingip) changes so " "nova can update its cache." msgstr "" -"埠資料 (fixed_ips/floatingip) 變更時,將通知傳送至 Nova,以便 Nova 可以更新其" -"快取。" +"當埠資料 (fixed_ips/floatingip) 變更時,將通知傳送至 Nova,以便 Nova 可以更新" +"其快取。" msgid "Send notification to nova when port status changes" -msgstr "埠狀態變更時,將通知傳送至 Nova" +msgstr "當埠狀態變更時,將通知傳送至 Nova" msgid "" "Send this many gratuitous ARPs for HA setup, if less than or equal to 0, the " @@ -3101,7 +3096,7 @@ msgid "Service Profile is not enabled." msgstr "未啟用服務設定檔。" msgid "Service Profile needs either a driver or metainfo." -msgstr "服務設定檔需要驅動程式或 metainfo。" +msgstr "服務設定檔需要驅動程式或 meta 資訊。" #, python-format msgid "" @@ -3121,7 +3116,7 @@ msgid "" "If value is set to 0, rpc timeout won't be changed" msgstr "" "在代理程式接收 SIGTERM 之後為新 RPC 呼叫設定新逾時(以秒為單位)。如果值設定" -"為 0,RPC 逾時將不會變更" +"為 0,則 RPC 逾時將不會變更" msgid "" "Set or un-set the don't fragment (DF) bit on outgoing IP packet carrying GRE/" @@ -3134,7 +3129,7 @@ msgid "" "Set or un-set the tunnel header checksum on outgoing IP packet carrying GRE/" "VXLAN tunnel." msgstr "" -"在送出的 IP 封包(攜帶 GRE/VXLAN 通道)上,設定或取消設定通道標頭總和檢查。" +"在帶有 GRE/VXLAN 通道的送出 IP 封包上,設定或取消設定通道標頭總和檢查。" msgid "Shared address scope can't be unshared" msgstr "無法將已共用的位址範圍取消共用" @@ -3142,7 +3137,7 @@ msgstr "無法將已共用的位址範圍取消共用" msgid "" "Specifying 'tenant_id' other than authenticated tenant in request requires " "admin privileges" -msgstr "在要求中指定已鑑別 Tenant 之外的 'tenant_id' 時需要管理者專用權" +msgstr "在要求中指定除已鑑別承租人外的其他 'tenant_id' 時,需要管理者專用權" msgid "String prefix used to match IPset names." msgstr "用來符合 IPset 名稱的字串字首。" @@ -3166,7 +3161,7 @@ msgid "Subnet pool has existing allocations" msgstr "子網路儲存區具有現有的配置" msgid "Subnet used for the l3 HA admin network." -msgstr "用於 l3 HA 管理網路的子網路。" +msgstr "用於 L3 HA 管理網路的子網路。" msgid "" "Subnets hosted on the same network must be allocated from the same subnet " @@ -3210,16 +3205,16 @@ msgstr "找不到標記 %(tag)s。" #, python-format msgid "Tenant %(tenant_id)s not allowed to create %(resource)s on this network" -msgstr "Tenant %(tenant_id)s 不可在此網路上建立 %(resource)s" +msgstr "不容許承租人 %(tenant_id)s 在此網路上建立 %(resource)s" msgid "Tenant id for connecting to designate in admin context" -msgstr "用於連接以在管理環境定義中指定的租戶 ID" +msgstr "用於連接以在管理環境定義中指定的承租人 ID" msgid "Tenant name for connecting to designate in admin context" -msgstr "用於連接以在管理環境定義中指定的租戶名稱" +msgstr "用於連接以在管理環境定義中指定的承租人名稱" msgid "Tenant network creation is not enabled." -msgstr "未啟用 Tenant 網路建立作業。" +msgstr "未啟用承租人網路建立作業。" msgid "Tenant-id was missing from quota request." msgstr "配額要求中遺漏了 Tenant-id。" @@ -3236,8 +3231,8 @@ msgid "" "transient notification or RPC errors. The interval is number of seconds " "between attempts." msgstr "" -"DHCP 代理程式會將自己的狀態與 Neutron 進行同步,以從任何暫時性通知或 RPC 錯誤" -"進行回復。間隔為兩次嘗試之間的秒數。" +"DHCP 代理程式會重新將自己的狀態與 Neutron 進行同步,以從任何暫時性通知或 RPC " +"錯誤進行回復。間隔為兩次嘗試之間的秒數。" msgid "" "The DHCP server can assist with providing metadata support on isolated " @@ -3282,7 +3277,7 @@ msgstr "配置儲存區 %(pool)s 跨越了子網路 CIDR %(subnet_cidr)s。" msgid "" "The attribute '%(attr)s' is reference to other resource, can't used by sort " "'%(resource)s'" -msgstr "屬性 '%(attr)s' 是對其他資源的參照,無法由排序 '%(resource)s' 使用" +msgstr "屬性 '%(attr)s' 是對其他資源的參照,無法供排序 '%(resource)s' 使用" msgid "" "The base MAC address Neutron will use for VIFs. The first 3 octets will " @@ -3301,10 +3296,10 @@ msgid "" "The default is 3 octet" msgstr "" "Neutron 用於唯一 DVR 實例的基本 MAC 位址。前 3 個八位元組將保持不變。如果第 " -"4 個八位元組不是 00,則也將使用該八位元組。其他個項將隨機產" -"生。'dvr_base_mac' 必須與 'base_mac' 不同,以避免將它們與對承租人埠配置的 " -"MAC 混合。4 個八位元組範例如下:dvr_base_mac = fa:16:3f:4f:00:00。預設值為 3 " -"個八位元組" +"4 個八位元組不是 00,則也將使用該八位元組。其他各項將隨機產" +"生。'dvr_base_mac' *必須*與 'base_mac' 不同,以避免將它們與對承租人埠配置的 " +"MAC 混合。4 個八位元組的範例如下:dvr_base_mac = fa:16:3f:4f:00:00。預設值為 " +"3 個八位元組" msgid "" "The connection string for the native OVSDB backend. Requires the native " @@ -3321,9 +3316,9 @@ msgid "" "must also include one or more valid DNS labels to the left of " "'%(dns_domain)s'" msgstr "" -"所傳遞的 dns_name 是 FQDN。它的更高階標籤必須等於neutron.conf 中的 " -"dns_domain 選項,後者已經設定為 '%(dns_domain)s'。它還必須包括下列項目左側的" -"一個以上有效 DNS 標籤:'%(dns_domain)s'" +"所傳遞的 dns_name 是 FQDN。它的更高階標籤必須等於 neutron.conf 中的 " +"dns_domain 選項,後者已經設定為 '%(dns_domain)s'。它還必須包括 " +"'%(dns_domain)s' 左側的一個以上有效 DNS 標籤" #, python-format msgid "" @@ -3335,8 +3330,8 @@ msgid "" msgstr "" "所傳遞的 dns_name 是 PQDN,並且它的大小是 '%(dns_name_len)s'。neutron.conf 中" "的 dns_domain 選項已設定為 %(dns_domain)s,長度為'%(higher_labels_len)s'。當" -"這兩者連結以形成 FQDN(末尾使用'.')時,所產生的長度會超過大小上" -"限'%(fqdn_max_len)s'" +"這兩者連結以形成 FQDN(末尾使用 '.')時,所產生的長度會超過大小上限 " +"'%(fqdn_max_len)s'" msgid "The driver used to manage the DHCP server." msgstr "用於管理 DHCP 伺服器的驅動程式。" @@ -3356,14 +3351,14 @@ msgid "" "The following device_id %(device_id)s is not owned by your tenant or matches " "another tenants router." msgstr "" -"下列 device_id %(device_id)s 不是由您的承租人所擁有者,或者與另一個承租人路由" -"器相符。" +"下列 device_id %(device_id)s 不是由您的承租人所擁有,或者與另一個承租人路由器" +"相符。" msgid "The host IP to bind to" msgstr "要連結至的主機 IP" msgid "The interface for interacting with the OVSDB" -msgstr "用於與 OVSDB 互動的介面" +msgstr "用來與 OVSDB 互動的介面" msgid "" "The maximum number of items returned in a single response, value was " @@ -3403,7 +3398,7 @@ msgstr "輪詢本端裝置變更之間代理程式將等待的秒數。" msgid "" "The number of seconds to wait before respawning the ovsdb monitor after " "losing communication with it." -msgstr "與 OVSDB 監視器的通訊中斷後重新大量產生OVSDB 監視器之前等待的秒數。" +msgstr "與 OVSDB 監視器的通訊中斷後重新大量產生 OVSDB 監視器之前等待的秒數。" msgid "The number of sort_keys and sort_dirs must be same" msgstr "sort_key 數目及 sort_dir 數目必須相同" @@ -3475,12 +3470,12 @@ msgid "" "must be used for an L3 agent running on a centralized node (or in single-" "host deployments, e.g. devstack)" msgstr "" -"代理程式的工作中模式。所容許的模式為:「舊式」- 這種模式會將現有行為保留在集" -"中式網路節點上用於部署L3 代理程式的位置,以提供 L3 服務(例如 DNAT 和 " -"SNAT)。如果您不想採用 DVR,請使用這種模式。'dvr' - 這種模式會啟用DVR 功能," -"並且必須用於在計算主機上執行的 L3 代理程式。'dvr_snat' - 這種模式會啟用集中" -"式 SNAT 支援以及 DVR。這種模式必須用於在集中式節點上執行(或者在單一主機部屬" -"中執行,例如 devstack)的 L3 代理程式" +"代理程式的工作模式。所容許的模式為:「舊式」- 這種模式會將現有行為保留在集中" +"式網路節點上用於部署L3 代理程式的位置,以提供 L3 服務(例如 DNAT 和 SNAT)。" +"如果您不想採用 DVR,請使用這種模式。'dvr' - 這種模式會啟用 DVR 功能,並且必須" +"用於在計算主機上執行的 L3 代理程式。'dvr_snat' - 這種模式會啟用集中式 SNAT 支" +"援以及 DVR。這種模式必須用於在集中式節點上執行(或者在單一主機部屬中執行,例" +"如 devstack)的 L3 代理程式" msgid "" "There are routers attached to this network that depend on this policy for " @@ -3508,7 +3503,7 @@ msgid "" "Timeout in seconds to wait for a single OpenFlow request. Used only for " "'native' driver." msgstr "" -"等待單個 OpenFlow 要求的逾時值(以秒為單位)。僅用於'native' 驅動程式。" +"等待單個 OpenFlow 要求的逾時值(以秒為單位)。僅用於 'native' 驅動程式。" msgid "" "Timeout in seconds to wait for the local switch connecting the controller. " @@ -3528,7 +3523,7 @@ msgid "" "True to delete all ports on all the OpenvSwitch bridges. False to delete " "ports created by Neutron on integration and external network bridges." msgstr "" -"如果為 True,則刪除所有 OpenvSwitch 橋接器上的所有埠。如果為 False,則刪除" +"如果為 True,則刪除所有 OpenvSwitch 橋接器上的所有埠。如果為 False,則刪除 " "Neutron 在整合及外部網路橋接器上建立的埠。" msgid "Tunnel IP value needed by the ML2 plugin" @@ -3541,14 +3536,14 @@ msgid "" "Type of the nova endpoint to use. This endpoint will be looked up in the " "keystone catalog and should be one of public, internal or admin." msgstr "" -"要使用之 Nova 端點的類型。此端點將在 Keystone 型錄予以查閱,並且應該是共用、" -"內部或管理的其中一個。" +"要使用之 Nova 端點的類型。此端點將在 Keystone 型錄中予以查閱,並且應該是共" +"用、內部或管理的其中一個。" msgid "URL for connecting to designate" msgstr "用於連接以指定的 URL" msgid "URL to database" -msgstr "資料庫 URL" +msgstr "資料庫的 URL" #, python-format msgid "Unable to access %s" @@ -3559,16 +3554,16 @@ msgid "" "Unable to allocate subnet with prefix length %(prefixlen)s, maximum allowed " "prefix is %(max_prefixlen)s." msgstr "" -"無法配置字首長度為 %(prefixlen)s 的子網路,容許的字首上限" -"為%(max_prefixlen)s。" +"無法配置字首長度為 %(prefixlen)s 的子網路,容許的字首上限為 " +"%(max_prefixlen)s。" #, python-format msgid "" "Unable to allocate subnet with prefix length %(prefixlen)s, minimum allowed " "prefix is %(min_prefixlen)s." msgstr "" -"無法配置字首長度為 %(prefixlen)s 的子網路,容許的字首下限" -"為%(min_prefixlen)s。" +"無法配置字首長度為 %(prefixlen)s 的子網路,容許的字首下限為 " +"%(min_prefixlen)s。" #, python-format msgid "Unable to calculate %(address_type)s address because of:%(reason)s" @@ -3657,19 +3652,19 @@ msgstr "無法在網路 %(net_id)s 上產生唯一 MAC 位址。" msgid "" "Unable to identify a target field from:%s. Match should be in the form " "%%()s" -msgstr "無法識別來自 %s 的目標欄位。相符項的格式應該為%%()s" +msgstr "無法識別來自 %s 的目標欄位。相符項的格式應該為 %%()s" msgid "Unable to provide external connectivity" msgstr "無法提供外部連線功能" msgid "Unable to provide tenant private network" -msgstr "無法提供租戶專用網路" +msgstr "無法提供承租人專用網路" #, python-format msgid "" "Unable to reconfigure sharing settings for network %(network)s. Multiple " "tenants are using it." -msgstr "無法重新配置網路 %(network)s 的共用設定。多個租戶正在使用該網路。" +msgstr "無法重新配置網路 %(network)s 的共用設定。多個承租人正在使用該網路。" #, python-format msgid "Unable to update address scope %(address_scope_id)s : %(reason)s" @@ -3805,7 +3800,7 @@ msgid "" "empty: agent effective user)." msgstr "" "在 meta 資料 Proxy 起始設定之後執行該 Proxy 的使用者(UID 或名稱)(如果為" -"空:則為代理程式有效使用者)。" +"空,則為代理程式有效使用者)。" msgid "User (uid or name) running this process after its initialization" msgstr "在此程序起始設定之後執行此程序的使用者(UID 或名稱)" @@ -3834,7 +3829,7 @@ msgid "" "Validation of dictionary's keys failed. Expected keys: %(expected_keys)s " "Provided keys: %(provided_keys)s" msgstr "" -"驗證字典索引鍵失敗。預期索引鍵:%(expected_keys)s提供的索引鍵:" +"驗證字典索引鍵失敗。預期索引鍵:%(expected_keys)s,提供的索引鍵:" "%(provided_keys)s" #, python-format @@ -3850,7 +3845,7 @@ msgid "" "Value of %(parameter)s has to be multiple of %(number)s, with maximum value " "of %(maximum)s and minimum value of %(minimum)s" msgstr "" -"值 %(parameter)s 必須是 %(number)s 的倍數,上限值為 %(maximum)s 且下限值為 " +"%(parameter)s 的值必須是 %(number)s 的倍數,上限值為 %(maximum)s 且下限值為 " "%(minimum)s" msgid "" @@ -3872,8 +3867,8 @@ msgid "" "Watch file log. Log watch should be disabled when metadata_proxy_user/group " "has no read/write permissions on metadata proxy log file." msgstr "" -"監看日誌檔。當 metadata_proxy_user/group 沒有對meta 資料 Proxy 日誌檔的讀寫許" -"可權時,應該停用日誌監看。" +"監看日誌檔。當 metadata_proxy_user/group 沒有對 meta 資料 Proxy 日誌檔的讀寫" +"許可權時,應該停用日誌監看。" msgid "" "When external_network_bridge is set, each L3 agent can be associated with no " @@ -3920,8 +3915,8 @@ msgstr "" "指派的鏈結本端位址 (LLA)。但是,IPv6 閘道位址需要用作預設路由的下一個中繼站。" "如果未在這裡配置 IPv6 閘道位址,(且僅當那時)則將會配置 Neutron 路由器以從上" "游路由器的路由器通告 (RA) 中取得其預設路由;在該情況下,也必須配置上游路由器" -"以傳送這些 RA。ipv6_gateway(如果已配置)應為上游路由器介面的 LLA。如果需要使" -"用廣域唯一位址 (GUA) 的下一個中繼站,則需要透過配置給網路的子網路來執行此配" +"以傳送這些 RA。ipv6_gateway(如果已配置)應該是上游路由器介面的 LLA。如果需要" +"使用廣域唯一位址 (GUA) 的下一個中繼站,則需要透過配置給網路的子網路來執行此配" "置,而不是透過此參數。" msgid "You must implement __call__" @@ -3930,13 +3925,13 @@ msgstr "必須實作 __call__" msgid "" "You must provide a config file for bridge - either --config-file or " "env[NEUTRON_TEST_CONFIG_FILE]" -msgstr "必須為橋接器提供配置檔:--config-file,或env[NEUTRON_TEST_CONFIG_FILE]" +msgstr "必須為橋接器提供配置檔:--config-file 或 env[NEUTRON_TEST_CONFIG_FILE]" msgid "You must provide a revision or relative delta" msgstr "必須提供修訂或相對差異" msgid "a subnetpool must be specified in the absence of a cidr" -msgstr "如果未指定 CIDR,則必須指定子網路儲存區" +msgstr "如果未指定 cidr,則必須指定子網路儲存區" msgid "add_ha_port cannot be called inside of a transaction." msgstr "無法在交易內呼叫 add_ha_port。" @@ -3965,7 +3960,7 @@ msgstr "不得同時提供 cidr 和 prefixlen" #, python-format msgid "dhcp_agents_per_network must be >= 1. '%s' is invalid." -msgstr "dhcp_agents_per_network 必須 >= 1。'%s' 無效。" +msgstr "dhcp_agents_per_network 必須大於或等於 1。'%s' 無效。" msgid "dns_domain cannot be specified without a dns_name" msgstr "如果未指定 dns_name,則無法指定 dns_domain" @@ -3993,7 +3988,7 @@ msgstr "對裝置 %(dev_name)s 執行的 IP 指令失敗:%(reason)s" #, python-format msgid "ip command failed: %(reason)s" -msgstr "ip 指令失敗:%(reason)s" +msgstr "IP 指令失敗:%(reason)s" #, python-format msgid "ip link capability %(capability)s is not supported" @@ -4016,8 +4011,7 @@ msgid "" "ipv6_ra_mode or ipv6_address_mode cannot be set when enable_dhcp is set to " "False." msgstr "" -"如果 enable_dhcp 設為 False,則 ipv6_ra_mode 和 ipv6_address_mode都無法進行設" -"定。" +"如果 enable_dhcp 設為 False,則無法設定 ipv6_ra_mode 和 ipv6_address_mode。" #, python-format msgid "" @@ -4026,7 +4020,7 @@ msgid "" "same value" msgstr "" "如果在 ipv6_address_mode 設為 '%(addr_mode)s' 時將 ipv6_ra_mode 設" -"為'%(ra_mode)s',則無效。如果兩個屬性同時設定,則它們的值必須相同" +"為'%(ra_mode)s',則無效。如果同時設定這兩個屬性,則它們的值必須相同" msgid "mac address update" msgstr "MAC 位址更新" @@ -4043,8 +4037,7 @@ msgstr "" msgid "" "min_l3_agents_per_router config parameter is not valid. It has to be equal " "to or more than %s for HA." -msgstr "" -"min_l3_agents_per_router 配置參數無效。該配置參數必須等於或大於 HA 的 %s。" +msgstr "min_l3_agents_per_router 配置參數無效。它必須等於或大於 HA 的 %s。" msgid "must provide exactly 2 arguments - cidr and MAC" msgstr "必須提供 2 個確切引數 - cidr 和 MAC" @@ -4082,7 +4075,7 @@ msgid "record" msgstr "記錄" msgid "respawn_interval must be >= 0 if provided." -msgstr "如果提供的話,則 respawn_interval 必須 >= 0。" +msgstr "如果提供的話,則 respawn_interval 必須大於或等於 0。" #, python-format msgid "segmentation_id out of range (%(min)s through %(max)s)" @@ -4099,8 +4092,8 @@ msgid "" "subnetpool %(subnetpool_id)s cannot be updated when associated with shared " "address scope %(address_scope_id)s" msgstr "" -"子網路儲存區 %(subnetpool_id)s 在下列情況下無法更新:與共用位址範圍 " -"%(address_scope_id)s 相關聯時" +"當子網路儲存區 %(subnetpool_id)s 與共用位址範圍 %(address_scope_id)s 相關聯" +"時,無法更新此子網路儲存區" msgid "subnetpool_id and use_default_subnetpool cannot both be specified" msgstr "不能同時指定 subnetpool_id 和 use_default_subnetpool" @@ -4119,5 +4112,5 @@ msgid "" "uuid provided from the command line so external_process can track us via /" "proc/cmdline interface." msgstr "" -"已從指令行提供了 UUID,因此, external_process 可以透過/proc/cmdline 介面對我" -"們進行追蹤。" +"已從指令行提供了 UUID,因此, external_process 可以透過 /proc/cmdline 介面對" +"我們進行追蹤。" From a323769143001d67fd1b3b4ba294e59accd09e0e Mon Sep 17 00:00:00 2001 From: Ryan Moats Date: Tue, 20 Oct 2015 15:51:37 +0000 Subject: [PATCH 51/51] Revert "Improve performance of ensure_namespace" This reverts commit 81823e86328e62850a89aef9f0b609bfc0a6dacd. Unneeded optimization: this commit only improves execution time on the order of milliseconds, which is less than 1% of the total router update execution time at the network node. This also Closes-bug: #1574881 Change-Id: Icbcdf4725ba7d2e743bb6761c9799ae436bd953b --- neutron/agent/linux/ip_lib.py | 12 ++--- .../functional/agent/linux/test_ip_lib.py | 6 --- neutron/tests/unit/agent/linux/test_ip_lib.py | 45 ++++++++++++------- 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/neutron/agent/linux/ip_lib.py b/neutron/agent/linux/ip_lib.py index 6e193427d3f..022463f6687 100644 --- a/neutron/agent/linux/ip_lib.py +++ b/neutron/agent/linux/ip_lib.py @@ -40,7 +40,6 @@ OPTS = [ LOOPBACK_DEVNAME = 'lo' -IP_NETNS_PATH = '/var/run/netns' SYS_NET_PATH = '/sys/class/net' DEFAULT_GW_PATTERN = re.compile(r"via (\S+)") METRIC_PATTERN = re.compile(r"metric (\S+)") @@ -246,10 +245,7 @@ class IPWrapper(SubProcessBase): @classmethod def get_namespaces(cls): - if not cfg.CONF.AGENT.use_helper_for_ns_read: - return os.listdir(IP_NETNS_PATH) - - output = cls._execute([], 'netns', ['list'], run_as_root=True) + output = cls._execute([], 'netns', ('list',)) return [l.split()[0] for l in output.splitlines()] @@ -931,11 +927,9 @@ class IpNetnsCommand(IpCommandBase): log_fail_as_error=log_fail_as_error, **kwargs) def exists(self, name): - if not cfg.CONF.AGENT.use_helper_for_ns_read: - return name in os.listdir(IP_NETNS_PATH) - output = self._parent._execute( - ['o'], 'netns', ['list'], run_as_root=True) + ['o'], 'netns', ['list'], + run_as_root=cfg.CONF.AGENT.use_helper_for_ns_read) for line in [l.split()[0] for l in output.splitlines()]: if name == line: return True diff --git a/neutron/tests/functional/agent/linux/test_ip_lib.py b/neutron/tests/functional/agent/linux/test_ip_lib.py index 3389bcc1c2d..4be32098656 100644 --- a/neutron/tests/functional/agent/linux/test_ip_lib.py +++ b/neutron/tests/functional/agent/linux/test_ip_lib.py @@ -86,12 +86,6 @@ class IpLibTestFramework(functional_base.BaseSudoTestCase): class IpLibTestCase(IpLibTestFramework): - def test_namespace_exists(self): - namespace = self.useFixture(net_helpers.NamespaceFixture()) - self.assertTrue(namespace.ip_wrapper.netns.exists(namespace.name)) - namespace.destroy() - self.assertFalse(namespace.ip_wrapper.netns.exists(namespace.name)) - def test_device_exists(self): attr = self.generate_device_details() diff --git a/neutron/tests/unit/agent/linux/test_ip_lib.py b/neutron/tests/unit/agent/linux/test_ip_lib.py index 1fb3a4a30bf..d7bd6a79e9a 100644 --- a/neutron/tests/unit/agent/linux/test_ip_lib.py +++ b/neutron/tests/unit/agent/linux/test_ip_lib.py @@ -15,7 +15,6 @@ import mock import netaddr -from oslo_config import cfg import testtools from neutron.agent.common import utils # noqa @@ -284,37 +283,23 @@ class TestIpWrapper(base.BaseTestCase): def test_get_namespaces(self): self.execute.return_value = '\n'.join(NETNS_SAMPLE) - cfg.CONF.AGENT.use_helper_for_ns_read = True retval = ip_lib.IPWrapper.get_namespaces() self.assertEqual(retval, ['12345678-1234-5678-abcd-1234567890ab', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', 'cccccccc-cccc-cccc-cccc-cccccccccccc']) - self.execute.assert_called_once_with([], 'netns', ['list'], - run_as_root=True) + self.execute.assert_called_once_with([], 'netns', ('list',)) def test_get_namespaces_iproute2_4(self): self.execute.return_value = '\n'.join(NETNS_SAMPLE_IPROUTE2_4) - cfg.CONF.AGENT.use_helper_for_ns_read = True retval = ip_lib.IPWrapper.get_namespaces() self.assertEqual(retval, ['12345678-1234-5678-abcd-1234567890ab', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', 'cccccccc-cccc-cccc-cccc-cccccccccccc']) - self.execute.assert_called_once_with([], 'netns', ['list'], - run_as_root=True) - - @mock.patch('os.listdir', return_value=NETNS_SAMPLE) - def test_get_namespaces_listdir(self, mocked_listdir): - cfg.CONF.AGENT.use_helper_for_ns_read = False - retval = ip_lib.IPWrapper.get_namespaces() - self.assertEqual(retval, - ['12345678-1234-5678-abcd-1234567890ab', - 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', - 'cccccccc-cccc-cccc-cccc-cccccccccccc']) - mocked_listdir.assert_called_once_with(ip_lib.IP_NETNS_PATH) + self.execute.assert_called_once_with([], 'netns', ('list',)) def test_add_tuntap(self): ip_lib.IPWrapper().add_tuntap('tap0') @@ -1226,6 +1211,32 @@ class TestIpNetnsCommand(TestIPCmdBase): self.netns_cmd.delete('ns') self._assert_sudo([], ('delete', 'ns'), use_root_namespace=True) + def test_namespace_exists_use_helper(self): + self.config(group='AGENT', use_helper_for_ns_read=True) + retval = '\n'.join(NETNS_SAMPLE) + # need another instance to avoid mocking + netns_cmd = ip_lib.IpNetnsCommand(ip_lib.SubProcessBase()) + with mock.patch('neutron.agent.common.utils.execute') as execute: + execute.return_value = retval + self.assertTrue( + netns_cmd.exists('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb')) + execute.assert_called_once_with(['ip', '-o', 'netns', 'list'], + run_as_root=True, + log_fail_as_error=True) + + def test_namespace_doest_not_exist_no_helper(self): + self.config(group='AGENT', use_helper_for_ns_read=False) + retval = '\n'.join(NETNS_SAMPLE) + # need another instance to avoid mocking + netns_cmd = ip_lib.IpNetnsCommand(ip_lib.SubProcessBase()) + with mock.patch('neutron.agent.common.utils.execute') as execute: + execute.return_value = retval + self.assertFalse( + netns_cmd.exists('bbbbbbbb-1111-2222-3333-bbbbbbbbbbbb')) + execute.assert_called_once_with(['ip', '-o', 'netns', 'list'], + run_as_root=False, + log_fail_as_error=True) + def test_execute(self): self.parent.namespace = 'ns' with mock.patch('neutron.agent.common.utils.execute') as execute: