diff options
216 files changed, 5505 insertions, 8354 deletions
diff --git a/doc/source/admin/config-bgp-floating-ip-over-l2-segmented-network.rst b/doc/source/admin/config-bgp-floating-ip-over-l2-segmented-network.rst index 12fe3d534a..dcedcf827a 100644 --- a/doc/source/admin/config-bgp-floating-ip-over-l2-segmented-network.rst +++ b/doc/source/admin/config-bgp-floating-ip-over-l2-segmented-network.rst @@ -65,10 +65,10 @@ python3-neutron-dynamic-routing packages). On top of that, "segments" and "bgp" must be added to the list of plugins in service_plugins. For example in neutron.conf: - .. code-block:: ini +.. code-block:: ini - [DEFAULT] - service_plugins=router,metering,qos,trunk,segments,bgp + [DEFAULT] + service_plugins=router,metering,qos,trunk,segments,bgp The BGP agent @@ -89,36 +89,36 @@ associated to a dynamic-routing-agent (in our example, the dynamic-routing agents run on compute 1 and 4). Finally, the peer is added to the BGP speaker, so the speaker initiates a BGP session to the network equipment. - .. code-block:: console +.. code-block:: console - $ # Create a BGP peer to represent the switch 1, - $ # which runs FRR on 10.1.0.253 with AS 64601 - $ openstack bgp peer create \ - --peer-ip 10.1.0.253 \ - --remote-as 64601 \ - rack1-switch-1 + $ # Create a BGP peer to represent the switch 1, + $ # which runs FRR on 10.1.0.253 with AS 64601 + $ openstack bgp peer create \ + --peer-ip 10.1.0.253 \ + --remote-as 64601 \ + rack1-switch-1 - $ # Create a BGP speaker on compute-1 - $ BGP_SPEAKER_ID_COMPUTE_1=$(openstack bgp speaker create \ - --local-as 64999 --ip-version 4 mycloud-compute-1.example.com \ - --format value -c id) + $ # Create a BGP speaker on compute-1 + $ BGP_SPEAKER_ID_COMPUTE_1=$(openstack bgp speaker create \ + --local-as 64999 --ip-version 4 mycloud-compute-1.example.com \ + --format value -c id) - $ # Get the agent ID of the dragent running on compute 1 - $ BGP_AGENT_ID_COMPUTE_1=$(openstack network agent list \ - --host mycloud-compute-1.example.com --agent-type bgp \ - --format value -c ID) + $ # Get the agent ID of the dragent running on compute 1 + $ BGP_AGENT_ID_COMPUTE_1=$(openstack network agent list \ + --host mycloud-compute-1.example.com --agent-type bgp \ + --format value -c ID) - $ # Add the BGP speaker to the dragent of compute 1 - $ openstack bgp dragent add speaker \ - ${BGP_AGENT_ID_COMPUTE_1} ${BGP_SPEAKER_ID_COMPUTE_1} + $ # Add the BGP speaker to the dragent of compute 1 + $ openstack bgp dragent add speaker \ + ${BGP_AGENT_ID_COMPUTE_1} ${BGP_SPEAKER_ID_COMPUTE_1} - $ # Add the BGP peer to the speaker of compute 1 - $ openstack bgp speaker add peer \ - compute-1.example.com rack1-switch-1 + $ # Add the BGP peer to the speaker of compute 1 + $ openstack bgp speaker add peer \ + compute-1.example.com rack1-switch-1 - $ # Tell the speaker not to advertize tenant networks - $ openstack bgp speaker set \ - --no-advertise-tenant-networks mycloud-compute-1.example.com + $ # Tell the speaker not to advertize tenant networks + $ openstack bgp speaker set \ + --no-advertise-tenant-networks mycloud-compute-1.example.com It is possible to repeat this operation for a 2nd machine on the same rack, @@ -141,25 +141,23 @@ in each host, according to the rack names. On the compute or network nodes, this is done in /etc/neutron/plugins/ml2/openvswitch_agent.ini using the bridge_mappings directive: - .. code-block:: ini - - [ovs] - bridge_mappings = physnet-rack1:br-ex +.. code-block:: ini + [ovs] + bridge_mappings = physnet-rack1:br-ex All of the physical networks created this way must be added in the configuration of the neutron-server as well (ie: this is used by both neutron-api and neutron-rpc-server). For example, with 3 racks, here's how /etc/neutron/plugins/ml2/ml2_conf.ini should look like: - .. code-block:: ini - - [ml2_type_flat] - flat_networks = physnet-rack1,physnet-rack2,physnet-rack3 +.. code-block:: ini - [ml2_type_vlan] - network_vlan_ranges = physnet-rack1,physnet-rack2,physnet-rack3 + [ml2_type_flat] + flat_networks = physnet-rack1,physnet-rack2,physnet-rack3 + [ml2_type_vlan] + network_vlan_ranges = physnet-rack1,physnet-rack2,physnet-rack3 Once this is done, the provider network can be created, using physnet-rack1 as "physical network". @@ -171,40 +169,40 @@ Setting-up the provider network Everything that is in the provider network's scope will be advertised through BGP. Here is how to create the network scope: - .. code-block:: console +.. code-block:: console - $ # Create the address scope - $ openstack address scope create --share --ip-version 4 provider-addr-scope + $ # Create the address scope + $ openstack address scope create --share --ip-version 4 provider-addr-scope Then, the network can be ceated using the physical network name set above: - .. code-block:: console +.. code-block:: console - $ # Create the provider network that spawns over all racks - $ openstack network create --external --share \ - --provider-physical-network physnet-rack1 \ - --provider-network-type vlan \ - --provider-segment 11 \ - provider-network + $ # Create the provider network that spawns over all racks + $ openstack network create --external --share \ + --provider-physical-network physnet-rack1 \ + --provider-network-type vlan \ + --provider-segment 11 \ + provider-network This automatically creates a network AND a segment. Though by default, this segment has no name, which isn't convenient. This name can be changed though: - .. code-block:: console +.. code-block:: console - $ # Get the network ID: - $ PROVIDER_NETWORK_ID=$(openstack network show provider-network \ - --format value -c id) + $ # Get the network ID: + $ PROVIDER_NETWORK_ID=$(openstack network show provider-network \ + --format value -c id) - $ # Get the segment ID: - $ FIRST_SEGMENT_ID=$(openstack network segment list \ - --format csv -c ID -c Network | \ - q -H -d, "SELECT ID FROM - WHERE Network='${PROVIDER_NETWORK_ID}'") + $ # Get the segment ID: + $ FIRST_SEGMENT_ID=$(openstack network segment list \ + --format csv -c ID -c Network | \ + q -H -d, "SELECT ID FROM - WHERE Network='${PROVIDER_NETWORK_ID}'") - $ # Set the 1st segment name, matching the rack name - $ openstack network segment set --name segment-rack1 ${FIRST_SEGMENT_ID} + $ # Set the 1st segment name, matching the rack name + $ openstack network segment set --name segment-rack1 ${FIRST_SEGMENT_ID} Setting-up the 2nd segment @@ -213,15 +211,15 @@ Setting-up the 2nd segment The 2nd segment, which will be attached to our provider network, is created this way: - .. code-block:: console +.. code-block:: console - $ # Create the 2nd segment, matching the 2nd rack name - $ openstack network segment create \ - --physical-network physnet-rack2 \ - --network-type vlan \ - --segment 13 \ - --network provider-network \ - segment-rack2 + $ # Create the 2nd segment, matching the 2nd rack name + $ openstack network segment create \ + --physical-network physnet-rack2 \ + --network-type vlan \ + --segment 13 \ + --network provider-network \ + segment-rack2 Setting-up the provider subnets for the BGP next HOP routing @@ -232,45 +230,45 @@ network is in use in the machines. In order to use the address scope, subnet pools must be used. Here is how to create the subnet pool with the two ranges to use later when creating the subnets: - .. code-block:: console +.. code-block:: console - $ # Create the provider subnet pool which includes all ranges for all racks - $ openstack subnet pool create \ - --pool-prefix 10.1.0.0/24 \ - --pool-prefix 10.2.0.0/24 \ - --address-scope provider-addr-scope \ - --share \ - provider-subnet-pool + $ # Create the provider subnet pool which includes all ranges for all racks + $ openstack subnet pool create \ + --pool-prefix 10.1.0.0/24 \ + --pool-prefix 10.2.0.0/24 \ + --address-scope provider-addr-scope \ + --share \ + provider-subnet-pool Then, this is how to create the two subnets. In this example, we are keeping the addresses in .1 for the gateway, .2 for the DHCP server, and .253 +.254, as these addresses will be used by the switches for the BGP announcements: - .. code-block:: console - - $ # Create the subnet for the physnet-rack-1, using the segment-rack-1, and - $ # the subnet_service_type network:floatingip_agent_gateway - $ openstack subnet create \ - --service-type 'network:floatingip_agent_gateway' \ - --subnet-pool provider-subnet-pool \ - --subnet-range 10.1.0.0/24 \ - --allocation-pool start=10.1.0.3,end=10.1.0.252 \ - --gateway 10.1.0.1 \ - --network provider-network \ - --network-segment segment-rack1 \ - provider-subnet-rack1 - - $ # The same, for the 2nd rack - $ openstack subnet create \ - --service-type 'network:floatingip_agent_gateway' \ - --subnet-pool provider-subnet-pool \ - --subnet-range 10.2.0.0/24 \ - --allocation-pool start=10.2.0.3,end=10.2.0.252 \ - --gateway 10.2.0.1 \ - --network provider-network \ - --network-segment segment-rack2 \ - provider-subnet-rack2 +.. code-block:: console + + $ # Create the subnet for the physnet-rack-1, using the segment-rack-1, and + $ # the subnet_service_type network:floatingip_agent_gateway + $ openstack subnet create \ + --service-type 'network:floatingip_agent_gateway' \ + --subnet-pool provider-subnet-pool \ + --subnet-range 10.1.0.0/24 \ + --allocation-pool start=10.1.0.3,end=10.1.0.252 \ + --gateway 10.1.0.1 \ + --network provider-network \ + --network-segment segment-rack1 \ + provider-subnet-rack1 + + $ # The same, for the 2nd rack + $ openstack subnet create \ + --service-type 'network:floatingip_agent_gateway' \ + --subnet-pool provider-subnet-pool \ + --subnet-range 10.2.0.0/24 \ + --allocation-pool start=10.2.0.3,end=10.2.0.252 \ + --gateway 10.2.0.1 \ + --network provider-network \ + --network-segment segment-rack2 \ + provider-subnet-rack2 Note the service types. network:floatingip_agent_gateway makes sure that these @@ -285,21 +283,21 @@ This is to be repeated each time a new subnet must be created for floating IPs and router gateways. First, the range is added in the subnet pool, then the subnet itself is created: - .. code-block:: console +.. code-block:: console - $ # Add a new prefix in the subnet pool for the floating IPs: - $ openstack subnet pool set \ - --pool-prefix 203.0.113.0/24 \ - provider-subnet-pool + $ # Add a new prefix in the subnet pool for the floating IPs: + $ openstack subnet pool set \ + --pool-prefix 203.0.113.0/24 \ + provider-subnet-pool - $ # Create the floating IP subnet - $ openstack subnet create vm-fip \ - --service-type 'network:routed' \ - --service-type 'network:floatingip' \ - --service-type 'network:router_gateway' \ - --subnet-pool provider-subnet-pool \ - --subnet-range 203.0.113.0/24 \ - --network provider-network + $ # Create the floating IP subnet + $ openstack subnet create vm-fip \ + --service-type 'network:routed' \ + --service-type 'network:floatingip' \ + --service-type 'network:router_gateway' \ + --subnet-pool provider-subnet-pool \ + --subnet-range 203.0.113.0/24 \ + --network provider-network The service-type network:routed ensures we're using BGP through the provider network to advertize the IPs. network:floatingip and network:router_gateway @@ -312,13 +310,13 @@ The provider network needs to be added to each of the BGP speakers. This means each time a new rack is setup, the provider network must be added to the 2 BGP speakers of that rack. - .. code-block:: console +.. code-block:: console - $ # Add the provider network to the BGP speakers. - $ openstack bgp speaker add network \ - mycloud-compute-1.example.com provider-network - $ openstack bgp speaker add network \ - mycloud-compute-4.example.com provider-network + $ # Add the provider network to the BGP speakers. + $ openstack bgp speaker add network \ + mycloud-compute-1.example.com provider-network + $ openstack bgp speaker add network \ + mycloud-compute-4.example.com provider-network In this example, we've selected two compute nodes that are also running an @@ -332,68 +330,68 @@ This can be done by each customer. A subnet pool isn't mandatory, but it is nice to have. Typically, the customer network will not be advertized through BGP (but this can be done if needed). - .. code-block:: console - - $ # Create the tenant private network - $ openstack network create tenant-network - - $ # Self-service network pool: - $ openstack subnet pool create \ - --pool-prefix 192.168.130.0/23 \ - --share \ - tenant-subnet-pool - - $ # Self-service subnet: - $ openstack subnet create \ - --network tenant-network \ - --subnet-pool tenant-subnet-pool \ - --prefix-length 24 \ - tenant-subnet-1 - - $ # Create the router - $ openstack router create tenant-router - - $ # Add the tenant subnet to the tenant router - $ openstack router add subnet \ - tenant-router tenant-subnet-1 - - $ # Set the router's default gateway. This will use one public IP. - $ openstack router set \ - --external-gateway provider-network tenant-router - - $ # Create a first VM on the tenant subnet - $ openstack server create --image debian-10.5.0-openstack-amd64.qcow2 \ - --flavor cpu2-ram6-disk20 \ - --nic net-id=tenant-network \ - --key-name yubikey-zigo \ - test-server-1 - - $ # Eventually, add a floating IP - $ openstack floating ip create provider-network - +---------------------+--------------------------------------+ - | Field | Value | - +---------------------+--------------------------------------+ - | created_at | 2020-12-15T11:48:36Z | - | description | | - | dns_domain | None | - | dns_name | None | - | fixed_ip_address | None | - | floating_ip_address | 203.0.113.17 | - | floating_network_id | 859f5302-7b22-4c50-92f8-1f71d6f3f3f4 | - | id | 01de252b-4b78-4198-bc28-1328393bf084 | - | name | 203.0.113.17 | - | port_details | None | - | port_id | None | - | project_id | d71a5d98aef04386b57736a4ea4f3644 | - | qos_policy_id | None | - | revision_number | 0 | - | router_id | None | - | status | DOWN | - | subnet_id | None | - | tags | [] | - | updated_at | 2020-12-15T11:48:36Z | - +---------------------+--------------------------------------+ - $ openstack server add floating ip test-server-1 203.0.113.17 +.. code-block:: console + + $ # Create the tenant private network + $ openstack network create tenant-network + + $ # Self-service network pool: + $ openstack subnet pool create \ + --pool-prefix 192.168.130.0/23 \ + --share \ + tenant-subnet-pool + + $ # Self-service subnet: + $ openstack subnet create \ + --network tenant-network \ + --subnet-pool tenant-subnet-pool \ + --prefix-length 24 \ + tenant-subnet-1 + + $ # Create the router + $ openstack router create tenant-router + + $ # Add the tenant subnet to the tenant router + $ openstack router add subnet \ + tenant-router tenant-subnet-1 + + $ # Set the router's default gateway. This will use one public IP. + $ openstack router set \ + --external-gateway provider-network tenant-router + + $ # Create a first VM on the tenant subnet + $ openstack server create --image debian-10.5.0-openstack-amd64.qcow2 \ + --flavor cpu2-ram6-disk20 \ + --nic net-id=tenant-network \ + --key-name yubikey-zigo \ + test-server-1 + + $ # Eventually, add a floating IP + $ openstack floating ip create provider-network + +---------------------+--------------------------------------+ + | Field | Value | + +---------------------+--------------------------------------+ + | created_at | 2020-12-15T11:48:36Z | + | description | | + | dns_domain | None | + | dns_name | None | + | fixed_ip_address | None | + | floating_ip_address | 203.0.113.17 | + | floating_network_id | 859f5302-7b22-4c50-92f8-1f71d6f3f3f4 | + | id | 01de252b-4b78-4198-bc28-1328393bf084 | + | name | 203.0.113.17 | + | port_details | None | + | port_id | None | + | project_id | d71a5d98aef04386b57736a4ea4f3644 | + | qos_policy_id | None | + | revision_number | 0 | + | router_id | None | + | status | DOWN | + | subnet_id | None | + | tags | [] | + | updated_at | 2020-12-15T11:48:36Z | + +---------------------+--------------------------------------+ + $ openstack server add floating ip test-server-1 203.0.113.17 Cumulus switch configuration ---------------------------- @@ -409,38 +407,38 @@ that works (at least with Cumulus switches). Here's how. In /etc/network/switchd.conf we change this: - .. code-block:: ini +.. code-block:: ini - # configure a route instead of a neighbor with the same ip/mask - #route.route_preferred_over_neigh = FALSE - route.route_preferred_over_neigh = TRUE + # configure a route instead of a neighbor with the same ip/mask + #route.route_preferred_over_neigh = FALSE + route.route_preferred_over_neigh = TRUE and then simply restart switchd: - .. code-block:: console +.. code-block:: console - systemctl restart switchd + systemctl restart switchd This reboots the switch ASIC of the switch, so it may be a dangerous thing to do with no switch redundancy (so be careful when doing it). The completely safe procedure, if having 2 switches per rack, looks like this: - .. code-block:: console +.. code-block:: console - # save clagd priority - OLDPRIO=$(clagctl status | sed -r -n 's/.*Our.*Role: ([0-9]+) 0.*/\1/p') - # make sure that this switch is not the primary clag switch. otherwise the - # secondary switch will also shutdown all interfaces when loosing contact - # with the primary switch. - clagctl priority 16535 + # save clagd priority + OLDPRIO=$(clagctl status | sed -r -n 's/.*Our.*Role: ([0-9]+) 0.*/\1/p') + # make sure that this switch is not the primary clag switch. otherwise the + # secondary switch will also shutdown all interfaces when loosing contact + # with the primary switch. + clagctl priority 16535 - # tell neighbors to not route through this router - vtysh - vtysh# router bgp 64999 - vtysh# bgp graceful-shutdown - vtysh# exit - systemctl restart switchd - clagctl priority $OLDPRIO + # tell neighbors to not route through this router + vtysh + vtysh# router bgp 64999 + vtysh# bgp graceful-shutdown + vtysh# exit + systemctl restart switchd + clagctl priority $OLDPRIO Verification ------------ @@ -449,16 +447,16 @@ If everything goes well, the floating IPs are advertized over BGP through the provider network. Here is an example with 4 VMs deployed on 2 racks. Neutron is here picking-up IPs on the segmented network as Nexthop. - .. code-block:: console - - $ # Check the advertized routes: - $ openstack bgp speaker list advertised routes \ - mycloud-compute-4.example.com - +-----------------+-----------+ - | Destination | Nexthop | - +-----------------+-----------+ - | 203.0.113.17/32 | 10.1.0.48 | - | 203.0.113.20/32 | 10.1.0.65 | - | 203.0.113.40/32 | 10.2.0.23 | - | 203.0.113.55/32 | 10.2.0.35 | - +-----------------+-----------+ +.. code-block:: console + + $ # Check the advertized routes: + $ openstack bgp speaker list advertised routes \ + mycloud-compute-4.example.com + +-----------------+-----------+ + | Destination | Nexthop | + +-----------------+-----------+ + | 203.0.113.17/32 | 10.1.0.48 | + | 203.0.113.20/32 | 10.1.0.65 | + | 203.0.113.40/32 | 10.2.0.23 | + | 203.0.113.55/32 | 10.2.0.35 | + +-----------------+-----------+ diff --git a/doc/source/admin/config-dhcp-ha.rst b/doc/source/admin/config-dhcp-ha.rst index 82780551b7..fcfbc87d40 100644 --- a/doc/source/admin/config-dhcp-ha.rst +++ b/doc/source/admin/config-dhcp-ha.rst @@ -441,6 +441,38 @@ To test the HA of DHCP agent: #. Start DHCP agent on HostB. The VM gets the wanted IP again. +No HA for metadata service on isolated networks +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +All Neutron backends using the DHCP agent can also provide `metadata service +<https://docs.openstack.org/nova/latest/user/metadata.html>`_ in isolated +networks (i.e. networks without a router). In this case the DHCP agent manages +the metadata service (see config option `enable_isolated_metadata +<https://docs.openstack.org/neutron/latest/configuration/dhcp-agent.html#DEFAULT.enable_isolated_metadata>`_). + +Note however that the metadata service is only redundant for IPv4, and not +IPv6, even when the DHCP service is configured to be highly available +(config option `dhcp_agents_per_network +<https://docs.openstack.org/neutron/latest/configuration/neutron.html#DEFAULT.dhcp_agents_per_network>`_ +> 1). This is because the DHCP agent will insert a route to the well known +metadata IPv4 address (`169.254.169.254`) via its own IP address, so it will +be reachable as long as the DHCP service is available at that IP address. +This also means that recovery after a failure is tied to the renewal of the +DHCP lease, since that route will only change if the DHCP server for a VM +changes. + +With IPv6, the well known metadata IPv6 address (`fe80::a9fe:a9fe`) is used, +but directly configured in the DHCP agent network namespace. +Due to the enforcement of duplicate address detection (DAD), this address +can only be configured in at most one DHCP network namespaces at any time. +See `RFC 4862 <https://www.rfc-editor.org/rfc/rfc4862#section-5.4>`_ for +details on the DAD process. + +For this reason, even when you have multiple DHCP agents, an arbitrary one +(where the metadata IPv6 address is not in `dadfailed` state) will serve all +metadata requests over IPv6. When that metadata service instance becomes +unreachable there is no failover and the service will become unreachable. + Disabling and removing an agent ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/source/admin/config-ipv6.rst b/doc/source/admin/config-ipv6.rst index 65b5fb9a41..8f2395f6fb 100644 --- a/doc/source/admin/config-ipv6.rst +++ b/doc/source/admin/config-ipv6.rst @@ -195,8 +195,8 @@ Project network considerations Dataplane --------- -Both the Linux bridge and the Open vSwitch dataplane modules support -forwarding IPv6 +All dataplane modules, including OVN, Open vSwitch and Linux bridge, +support forwarding IPv6 packets amongst the guests and router ports. Similar to IPv4, there is no special configuration or setup required to enable the dataplane to properly forward packets from the source to the destination using IPv6. Note that these @@ -204,6 +204,15 @@ dataplanes will forward Link-local Address (LLA) packets between hosts on the same network just fine without any participation or setup by OpenStack components after the ports are all connected and MAC addresses learned. +.. warning:: + The only exception to this is the setting of the MTU value on + the network an IPv6 subnet is created on. If the MTU is less than + 1280 octets (the minimum link MTU value specified in + `RFC 8200 <https://www.rfc-editor.org/rfc/rfc8200>`__), then it + could lead to issues configuring both IPv6 and IPv4 addresses on + the network, leaving the subnets unusable. For that reason, the API + validates the MTU value when subnets are created to avoid this issue. + Addresses for subnets --------------------- diff --git a/doc/source/admin/config-logging.rst b/doc/source/admin/config-logging.rst index 6cd7ca2afe..ba1953738c 100644 --- a/doc/source/admin/config-logging.rst +++ b/doc/source/admin/config-logging.rst @@ -1,328 +1,328 @@ -.. _config-logging:
-
-================================
-Neutron Packet Logging Framework
-================================
-
-Packet logging service is designed as a Neutron plug-in that captures network
-packets for relevant resources (e.g. security group or firewall group) when the
-registered events occur.
-
-.. image:: figures/logging-framework.png
- :width: 100%
- :alt: Packet Logging Framework
-
-Supported loggable resource types
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-From Rocky release, both of ``security_group`` and ``firewall_group`` are
-supported as resource types in Neutron packet logging framework.
-
-
-Service Configuration
-~~~~~~~~~~~~~~~~~~~~~
-
-To enable the logging service, follow the below steps.
-
-#. On Neutron controller node, add ``log`` to ``service_plugins`` setting in
- ``/etc/neutron/neutron.conf`` file. For example:
-
- .. code-block:: none
-
- service_plugins = router,metering,log
-
-#. To enable logging service for ``security_group`` in Layer 2, add ``log`` to
- option ``extensions`` in section ``[agent]`` in ``/etc/neutron/plugins/ml2/ml2_conf.ini``
- for controller node and in ``/etc/neutron/plugins/ml2/openvswitch_agent.ini``
- for compute/network nodes. For example:
-
- .. code-block:: ini
-
- [agent]
- extensions = log
-
- .. note::
-
- Fwaas v2 log is currently only supported by openvswitch, the firewall
- logging driver of linuxbridge is not implemented.
-
-#. To enable logging service for ``firewall_group`` in Layer 3, add
- ``fwaas_v2_log`` to option ``extensions`` in section ``[AGENT]`` in
- ``/etc/neutron/l3_agent.ini`` for network nodes. For example:
-
- .. code-block:: ini
-
- [AGENT]
- extensions = fwaas_v2,fwaas_v2_log
-
-#. On compute/network nodes, add configuration for logging service to
- ``[network_log]`` in ``/etc/neutron/plugins/ml2/openvswitch_agent.ini`` and in
- ``/etc/neutron/l3_agent.ini`` as shown bellow:
-
- .. code-block:: ini
-
- [network_log]
- rate_limit = 100
- burst_limit = 25
- #local_output_log_base = <None>
-
- In which, ``rate_limit`` is used to configure the maximum number of packets
- to be logged per second (packets per second). When a high rate triggers
- ``rate_limit``, logging queues packets to be logged. ``burst_limit`` is
- used to configure the maximum of queued packets. And logged packets can be
- stored anywhere by using ``local_output_log_base``.
-
- .. note::
-
- - It requires at least ``100`` for ``rate_limit`` and at least ``25``
- for ``burst_limit``.
- - If ``rate_limit`` is unset, logging will log unlimited.
- - If we don't specify ``local_output_log_base``, logged packets will be
- stored in system journal like ``/var/log/syslog`` by default.
-
-Trusted projects policy.yaml configuration
-----------------------------------------------
-
-With the default ``/etc/neutron/policy.yaml``, administrators must set up
-resource logging on behalf of the cloud projects.
-
-If projects are trusted to administer their own loggable resources in their
-cloud, neutron's policy file ``policy.yaml`` can be modified to allow this.
-
-Modify ``/etc/neutron/policy.yaml`` entries as follows:
-
-.. code-block:: none
-
- "get_loggable_resources": "rule:regular_user",
- "create_log": "rule:regular_user",
- "get_log": "rule:regular_user",
- "get_logs": "rule:regular_user",
- "update_log": "rule:regular_user",
- "delete_log": "rule:regular_user",
-
-Service workflow for Operator
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-#. To check the loggable resources that are supported by framework:
-
- .. code-block:: console
-
- $ openstack network loggable resources list
- +-----------------+
- | Supported types |
- +-----------------+
- | security_group |
- | firewall_group |
- +-----------------+
-
- .. note::
-
- - In VM ports, logging for ``security_group`` in currently works with
- ``openvswitch`` firewall driver only. ``linuxbridge`` is under
- development.
- - Logging for ``firewall_group`` works on internal router ports only. VM
- ports would be supported in the future.
-
-#. Log creation:
-
- * Create a logging resource with an appropriate resource type
-
- .. code-block:: console
-
- $ openstack network log create --resource-type security_group \
- --description "Collecting all security events" \
- --event ALL Log_Created
- +-----------------+------------------------------------------------+
- | Field | Value |
- +-----------------+------------------------------------------------+
- | Description | Collecting all security events |
- | Enabled | True |
- | Event | ALL |
- | ID | 8085c3e6-0fa2-4954-b5ce-ff6207931b6d |
- | Name | Log_Created |
- | Project | 02568bd62b414221956f15dbe9527d16 |
- | Resource | None |
- | Target | None |
- | Type | security_group |
- | created_at | 2017-07-05T02:56:43Z |
- | revision_number | 0 |
- | tenant_id | 02568bd62b414221956f15dbe9527d16 |
- | updated_at | 2017-07-05T02:56:43Z |
- +-----------------+------------------------------------------------+
-
- .. warning::
-
- In the case of ``--resource`` and ``--target`` are not specified from the
- request, these arguments will be assigned to ``ALL`` by default. Hence,
- there is an enormous range of log events will be created.
-
- * Create logging resource with a given resource (sg1 or fwg1)
-
- .. code-block:: console
-
- $ openstack network log create my-log --resource-type security_group --resource sg1
- $ openstack network log create my-log --resource-type firewall_group --resource fwg1
-
- * Create logging resource with a given target (portA)
-
- .. code-block:: console
-
- $ openstack network log create my-log --resource-type security_group --target portA
-
- * Create logging resource for only the given target (portB) and the given
- resource (sg1 or fwg1)
-
- .. code-block:: console
-
- $ openstack network log create my-log --resource-type security_group --target portB --resource sg1
- $ openstack network log create my-log --resource-type firewall_group --target portB --resource fwg1
-
- .. note::
-
- - The ``Enabled`` field is set to ``True`` by default. If enabled, logged
- events are written to the destination if ``local_output_log_base`` is
- configured or ``/var/log/syslog`` in default.
- - The ``Event`` field will be set to ``ALL`` if ``--event`` is not specified
- from log creation request.
-
-#. Enable/Disable log
-
- We can ``enable`` or ``disable`` logging objects at runtime. It means that
- it will apply to all registered ports with the logging object immediately.
- For example:
-
- .. code-block:: console
-
- $ openstack network log set --disable Log_Created
- $ openstack network log show Log_Created
- +-----------------+------------------------------------------------+
- | Field | Value |
- +-----------------+------------------------------------------------+
- | Description | Collecting all security events |
- | Enabled | False |
- | Event | ALL |
- | ID | 8085c3e6-0fa2-4954-b5ce-ff6207931b6d |
- | Name | Log_Created |
- | Project | 02568bd62b414221956f15dbe9527d16 |
- | Resource | None |
- | Target | None |
- | Type | security_group |
- | created_at | 2017-07-05T02:56:43Z |
- | revision_number | 1 |
- | tenant_id | 02568bd62b414221956f15dbe9527d16 |
- | updated_at | 2017-07-05T03:12:01Z |
- +-----------------+------------------------------------------------+
-
-Logged events description
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Currently, packet logging framework supports to collect ``ACCEPT`` or ``DROP``
-or both events related to registered resources. As mentioned above, Neutron
-packet logging framework offers two loggable resources through the ``log``
-service plug-in: ``security_group`` and ``firewall_group``.
-
-The general characteristics of each event will be shown as the following:
-
-* Log every ``DROP`` event: Every ``DROP`` security events will be generated
- when an incoming or outgoing session is blocked by the security groups or
- firewall groups
-
-* Log an ``ACCEPT`` event: The ``ACCEPT`` security event will be generated only
- for each ``NEW`` incoming or outgoing session that is allowed by security
- groups or firewall groups. More details for the ``ACCEPT`` events are shown
- as bellow:
-
- * North/South ``ACCEPT``: For a North/South session there would be a single
- ``ACCEPT`` event irrespective of direction.
-
- * East/West ``ACCEPT``/``ACCEPT``: In an intra-project East/West session
- where the originating port allows the session and the destination port
- allows the session, i.e. the traffic is allowed, there would be two
- ``ACCEPT`` security events generated, one from the perspective of the
- originating port and one from the perspective of the destination port.
-
- * East/West ``ACCEPT``/``DROP``: In an intra-project East/West session
- initiation where the originating port allows the session and the
- destination port does not allow the session there would be ``ACCEPT``
- security events generated from the perspective of the originating port and
- ``DROP`` security events generated from the perspective of the destination
- port.
-
-#. The security events that are collected by security group should include:
-
- * A timestamp of the flow.
- * A status of the flow ``ACCEPT``/``DROP``.
- * An indication of the originator of the flow, e.g which project or log resource
- generated the events.
- * An identifier of the associated instance interface (neutron port id).
- * A layer 2, 3 and 4 information (mac, address, port, protocol, etc).
-
- * Security event record format:
-
- * Logged data of an ``ACCEPT`` event would look like:
-
- .. code-block:: console
-
- May 5 09:05:07 action=ACCEPT project_id=736672c700cd43e1bd321aeaf940365c
- log_resource_ids=['4522efdf-8d44-4e19-b237-64cafc49469b', '42332d89-df42-4588-a2bb-3ce50829ac51']
- vm_port=e0259ade-86de-482e-a717-f58258f7173f
- ethernet(dst='fa:16:3e:ec:36:32',ethertype=2048,src='fa:16:3e:50:aa:b5'),
- ipv4(csum=62071,dst='10.0.0.4',flags=2,header_length=5,identification=36638,offset=0,
- option=None,proto=6,src='172.24.4.10',tos=0,total_length=60,ttl=63,version=4),
- tcp(ack=0,bits=2,csum=15097,dst_port=80,offset=10,option=[TCPOptionMaximumSegmentSize(kind=2,length=4,max_seg_size=1460),
- TCPOptionSACKPermitted(kind=4,length=2), TCPOptionTimestamps(kind=8,length=10,ts_ecr=0,ts_val=196418896),
- TCPOptionNoOperation(kind=1,length=1), TCPOptionWindowScale(kind=3,length=3,shift_cnt=3)],
- seq=3284890090,src_port=47825,urgent=0,window_size=14600)
-
- * Logged data of a ``DROP`` event:
-
- .. code-block:: console
-
- May 5 09:05:07 action=DROP project_id=736672c700cd43e1bd321aeaf940365c
- log_resource_ids=['4522efdf-8d44-4e19-b237-64cafc49469b'] vm_port=e0259ade-86de-482e-a717-f58258f7173f
- ethernet(dst='fa:16:3e:ec:36:32',ethertype=2048,src='fa:16:3e:50:aa:b5'),
- ipv4(csum=62071,dst='10.0.0.4',flags=2,header_length=5,identification=36638,offset=0,
- option=None,proto=6,src='172.24.4.10',tos=0,total_length=60,ttl=63,version=4),
- tcp(ack=0,bits=2,csum=15097,dst_port=80,offset=10,option=[TCPOptionMaximumSegmentSize(kind=2,length=4,max_seg_size=1460),
- TCPOptionSACKPermitted(kind=4,length=2), TCPOptionTimestamps(kind=8,length=10,ts_ecr=0,ts_val=196418896),
- TCPOptionNoOperation(kind=1,length=1), TCPOptionWindowScale(kind=3,length=3,shift_cnt=3)],
- seq=3284890090,src_port=47825,urgent=0,window_size=14600)
-
-#. The events that are collected by firewall group should include:
-
- * A timestamp of the flow.
- * A status of the flow ``ACCEPT``/``DROP``.
- * The identifier of log objects that are collecting this event
- * An identifier of the associated instance interface (neutron port id).
- * A layer 2, 3 and 4 information (mac, address, port, protocol, etc).
-
- * Security event record format:
-
- * Logged data of an ``ACCEPT`` event would look like:
-
- .. code-block:: console
-
- Jul 26 14:46:20:
- action=ACCEPT, log_resource_ids=[u'2e030f3a-e93d-4a76-bc60-1d11c0f6561b'], port=9882c485-b808-4a34-a3fb-b537642c66b2
- pkt=ethernet(dst='fa:16:3e:8f:47:c5',ethertype=2048,src='fa:16:3e:1b:3e:67')
- ipv4(csum=47423,dst='10.10.1.16',flags=2,header_length=5,identification=27969,offset=0,option=None,proto=1,src='10.10.0.5',tos=0,total_length=84,ttl=63,version=4)
- icmp(code=0,csum=41376,data=echo(data='\xe5\xf2\xfej\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
- \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
- \x00\x00\x00\x00\x00\x00\x00',id=29185,seq=0),type=8)
-
- * Logged data of a ``DROP`` event:
-
- .. code-block:: console
-
- Jul 26 14:51:20:
- action=DROP, log_resource_ids=[u'2e030f3a-e93d-4a76-bc60-1d11c0f6561b'], port=9882c485-b808-4a34-a3fb-b537642c66b2
- pkt=ethernet(dst='fa:16:3e:32:7d:ff',ethertype=2048,src='fa:16:3e:28:83:51')
- ipv4(csum=17518,dst='10.10.0.5',flags=2,header_length=5,identification=57874,offset=0,option=None,proto=1,src='10.10.1.16',tos=0,total_length=84,ttl=63,version=4)
- icmp(code=0,csum=23772,data=echo(data='\x8a\xa0\xac|\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
- \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
- \x00\x00\x00\x00\x00\x00\x00',id=25601,seq=5),type=8)
-
-.. note::
-
- No other extraneous events are generated within the security event logs,
- e.g. no debugging data, etc.
+.. _config-logging: + +================================ +Neutron Packet Logging Framework +================================ + +Packet logging service is designed as a Neutron plug-in that captures network +packets for relevant resources (e.g. security group or firewall group) when the +registered events occur. + +.. image:: figures/logging-framework.png + :width: 100% + :alt: Packet Logging Framework + +Supported loggable resource types +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +From Rocky release, both of ``security_group`` and ``firewall_group`` are +supported as resource types in Neutron packet logging framework. + + +Service Configuration +~~~~~~~~~~~~~~~~~~~~~ + +To enable the logging service, follow the below steps. + +#. On Neutron controller node, add ``log`` to ``service_plugins`` setting in + ``/etc/neutron/neutron.conf`` file. For example: + + .. code-block:: none + + service_plugins = router,metering,log + +#. To enable logging service for ``security_group`` in Layer 2, add ``log`` to + option ``extensions`` in section ``[agent]`` in ``/etc/neutron/plugins/ml2/ml2_conf.ini`` + for controller node and in ``/etc/neutron/plugins/ml2/openvswitch_agent.ini`` + for compute/network nodes. For example: + + .. code-block:: ini + + [agent] + extensions = log + + .. note:: + + Fwaas v2 log is currently only supported by openvswitch, the firewall + logging driver of linuxbridge is not implemented. + +#. To enable logging service for ``firewall_group`` in Layer 3, add + ``fwaas_v2_log`` to option ``extensions`` in section ``[AGENT]`` in + ``/etc/neutron/l3_agent.ini`` for network nodes. For example: + + .. code-block:: ini + + [AGENT] + extensions = fwaas_v2,fwaas_v2_log + +#. On compute/network nodes, add configuration for logging service to + ``[network_log]`` in ``/etc/neutron/plugins/ml2/openvswitch_agent.ini`` and in + ``/etc/neutron/l3_agent.ini`` as shown below: + + .. code-block:: ini + + [network_log] + rate_limit = 100 + burst_limit = 25 + #local_output_log_base = <None> + + In which, ``rate_limit`` is used to configure the maximum number of packets + to be logged per second (packets per second). When a high rate triggers + ``rate_limit``, logging queues packets to be logged. ``burst_limit`` is + used to configure the maximum of queued packets. And logged packets can be + stored anywhere by using ``local_output_log_base``. + + .. note:: + + - It requires at least ``100`` for ``rate_limit`` and at least ``25`` + for ``burst_limit``. + - If ``rate_limit`` is unset, logging will log unlimited. + - If we don't specify ``local_output_log_base``, logged packets will be + stored in system journal like ``/var/log/syslog`` by default. + +Trusted projects policy.yaml configuration +---------------------------------------------- + +With the default ``/etc/neutron/policy.yaml``, administrators must set up +resource logging on behalf of the cloud projects. + +If projects are trusted to administer their own loggable resources in their +cloud, neutron's policy file ``policy.yaml`` can be modified to allow this. + +Modify ``/etc/neutron/policy.yaml`` entries as follows: + +.. code-block:: none + + "get_loggable_resources": "rule:regular_user", + "create_log": "rule:regular_user", + "get_log": "rule:regular_user", + "get_logs": "rule:regular_user", + "update_log": "rule:regular_user", + "delete_log": "rule:regular_user", + +Service workflow for Operator +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#. To check the loggable resources that are supported by framework: + + .. code-block:: console + + $ openstack network loggable resources list + +-----------------+ + | Supported types | + +-----------------+ + | security_group | + | firewall_group | + +-----------------+ + + .. note:: + + - In VM ports, logging for ``security_group`` in currently works with + ``openvswitch`` firewall driver only. ``linuxbridge`` is under + development. + - Logging for ``firewall_group`` works on internal router ports only. VM + ports would be supported in the future. + +#. Log creation: + + * Create a logging resource with an appropriate resource type + + .. code-block:: console + + $ openstack network log create --resource-type security_group \ + --description "Collecting all security events" \ + --event ALL Log_Created + +-----------------+------------------------------------------------+ + | Field | Value | + +-----------------+------------------------------------------------+ + | Description | Collecting all security events | + | Enabled | True | + | Event | ALL | + | ID | 8085c3e6-0fa2-4954-b5ce-ff6207931b6d | + | Name | Log_Created | + | Project | 02568bd62b414221956f15dbe9527d16 | + | Resource | None | + | Target | None | + | Type | security_group | + | created_at | 2017-07-05T02:56:43Z | + | revision_number | 0 | + | tenant_id | 02568bd62b414221956f15dbe9527d16 | + | updated_at | 2017-07-05T02:56:43Z | + +-----------------+------------------------------------------------+ + + .. warning:: + + In the case of ``--resource`` and ``--target`` are not specified from the + request, these arguments will be assigned to ``ALL`` by default. Hence, + there is an enormous range of log events will be created. + + * Create logging resource with a given resource (sg1 or fwg1) + + .. code-block:: console + + $ openstack network log create my-log --resource-type security_group --resource sg1 + $ openstack network log create my-log --resource-type firewall_group --resource fwg1 + + * Create logging resource with a given target (portA) + + .. code-block:: console + + $ openstack network log create my-log --resource-type security_group --target portA + + * Create logging resource for only the given target (portB) and the given + resource (sg1 or fwg1) + + .. code-block:: console + + $ openstack network log create my-log --resource-type security_group --target portB --resource sg1 + $ openstack network log create my-log --resource-type firewall_group --target portB --resource fwg1 + + .. note:: + + - The ``Enabled`` field is set to ``True`` by default. If enabled, logged + events are written to the destination if ``local_output_log_base`` is + configured or ``/var/log/syslog`` in default. + - The ``Event`` field will be set to ``ALL`` if ``--event`` is not specified + from log creation request. + +#. Enable/Disable log + + We can ``enable`` or ``disable`` logging objects at runtime. It means that + it will apply to all registered ports with the logging object immediately. + For example: + + .. code-block:: console + + $ openstack network log set --disable Log_Created + $ openstack network log show Log_Created + +-----------------+------------------------------------------------+ + | Field | Value | + +-----------------+------------------------------------------------+ + | Description | Collecting all security events | + | Enabled | False | + | Event | ALL | + | ID | 8085c3e6-0fa2-4954-b5ce-ff6207931b6d | + | Name | Log_Created | + | Project | 02568bd62b414221956f15dbe9527d16 | + | Resource | None | + | Target | None | + | Type | security_group | + | created_at | 2017-07-05T02:56:43Z | + | revision_number | 1 | + | tenant_id | 02568bd62b414221956f15dbe9527d16 | + | updated_at | 2017-07-05T03:12:01Z | + +-----------------+------------------------------------------------+ + +Logged events description +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Currently, packet logging framework supports to collect ``ACCEPT`` or ``DROP`` +or both events related to registered resources. As mentioned above, Neutron +packet logging framework offers two loggable resources through the ``log`` +service plug-in: ``security_group`` and ``firewall_group``. + +The general characteristics of each event will be shown as the following: + +* Log every ``DROP`` event: Every ``DROP`` security events will be generated + when an incoming or outgoing session is blocked by the security groups or + firewall groups + +* Log an ``ACCEPT`` event: The ``ACCEPT`` security event will be generated only + for each ``NEW`` incoming or outgoing session that is allowed by security + groups or firewall groups. More details for the ``ACCEPT`` events are shown + as bellow: + + * North/South ``ACCEPT``: For a North/South session there would be a single + ``ACCEPT`` event irrespective of direction. + + * East/West ``ACCEPT``/``ACCEPT``: In an intra-project East/West session + where the originating port allows the session and the destination port + allows the session, i.e. the traffic is allowed, there would be two + ``ACCEPT`` security events generated, one from the perspective of the + originating port and one from the perspective of the destination port. + + * East/West ``ACCEPT``/``DROP``: In an intra-project East/West session + initiation where the originating port allows the session and the + destination port does not allow the session there would be ``ACCEPT`` + security events generated from the perspective of the originating port and + ``DROP`` security events generated from the perspective of the destination + port. + +#. The security events that are collected by security group should include: + + * A timestamp of the flow. + * A status of the flow ``ACCEPT``/``DROP``. + * An indication of the originator of the flow, e.g which project or log resource + generated the events. + * An identifier of the associated instance interface (neutron port id). + * A layer 2, 3 and 4 information (mac, address, port, protocol, etc). + + * Security event record format: + + Logged data of an ``ACCEPT`` event would look like: + + .. code-block:: console + + May 5 09:05:07 action=ACCEPT project_id=736672c700cd43e1bd321aeaf940365c + log_resource_ids=['4522efdf-8d44-4e19-b237-64cafc49469b', '42332d89-df42-4588-a2bb-3ce50829ac51'] + vm_port=e0259ade-86de-482e-a717-f58258f7173f + ethernet(dst='fa:16:3e:ec:36:32',ethertype=2048,src='fa:16:3e:50:aa:b5'), + ipv4(csum=62071,dst='10.0.0.4',flags=2,header_length=5,identification=36638,offset=0, + option=None,proto=6,src='172.24.4.10',tos=0,total_length=60,ttl=63,version=4), + tcp(ack=0,bits=2,csum=15097,dst_port=80,offset=10,option=[TCPOptionMaximumSegmentSize(kind=2,length=4,max_seg_size=1460), + TCPOptionSACKPermitted(kind=4,length=2), TCPOptionTimestamps(kind=8,length=10,ts_ecr=0,ts_val=196418896), + TCPOptionNoOperation(kind=1,length=1), TCPOptionWindowScale(kind=3,length=3,shift_cnt=3)], + seq=3284890090,src_port=47825,urgent=0,window_size=14600) + + Logged data of a ``DROP`` event: + + .. code-block:: console + + May 5 09:05:07 action=DROP project_id=736672c700cd43e1bd321aeaf940365c + log_resource_ids=['4522efdf-8d44-4e19-b237-64cafc49469b'] vm_port=e0259ade-86de-482e-a717-f58258f7173f + ethernet(dst='fa:16:3e:ec:36:32',ethertype=2048,src='fa:16:3e:50:aa:b5'), + ipv4(csum=62071,dst='10.0.0.4',flags=2,header_length=5,identification=36638,offset=0, + option=None,proto=6,src='172.24.4.10',tos=0,total_length=60,ttl=63,version=4), + tcp(ack=0,bits=2,csum=15097,dst_port=80,offset=10,option=[TCPOptionMaximumSegmentSize(kind=2,length=4,max_seg_size=1460), + TCPOptionSACKPermitted(kind=4,length=2), TCPOptionTimestamps(kind=8,length=10,ts_ecr=0,ts_val=196418896), + TCPOptionNoOperation(kind=1,length=1), TCPOptionWindowScale(kind=3,length=3,shift_cnt=3)], + seq=3284890090,src_port=47825,urgent=0,window_size=14600) + +#. The events that are collected by firewall group should include: + + * A timestamp of the flow. + * A status of the flow ``ACCEPT``/``DROP``. + * The identifier of log objects that are collecting this event + * An identifier of the associated instance interface (neutron port id). + * A layer 2, 3 and 4 information (mac, address, port, protocol, etc). + + * Security event record format: + + Logged data of an ``ACCEPT`` event would look like: + + .. code-block:: console + + Jul 26 14:46:20: + action=ACCEPT, log_resource_ids=[u'2e030f3a-e93d-4a76-bc60-1d11c0f6561b'], port=9882c485-b808-4a34-a3fb-b537642c66b2 + pkt=ethernet(dst='fa:16:3e:8f:47:c5',ethertype=2048,src='fa:16:3e:1b:3e:67') + ipv4(csum=47423,dst='10.10.1.16',flags=2,header_length=5,identification=27969,offset=0,option=None,proto=1,src='10.10.0.5',tos=0,total_length=84,ttl=63,version=4) + icmp(code=0,csum=41376,data=echo(data='\xe5\xf2\xfej\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 + \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 + \x00\x00\x00\x00\x00\x00\x00',id=29185,seq=0),type=8) + + Logged data of a ``DROP`` event: + + .. code-block:: console + + Jul 26 14:51:20: + action=DROP, log_resource_ids=[u'2e030f3a-e93d-4a76-bc60-1d11c0f6561b'], port=9882c485-b808-4a34-a3fb-b537642c66b2 + pkt=ethernet(dst='fa:16:3e:32:7d:ff',ethertype=2048,src='fa:16:3e:28:83:51') + ipv4(csum=17518,dst='10.10.0.5',flags=2,header_length=5,identification=57874,offset=0,option=None,proto=1,src='10.10.1.16',tos=0,total_length=84,ttl=63,version=4) + icmp(code=0,csum=23772,data=echo(data='\x8a\xa0\xac|\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 + \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 + \x00\x00\x00\x00\x00\x00\x00',id=25601,seq=5),type=8) + +.. note:: + + No other extraneous events are generated within the security event logs, + e.g. no debugging data, etc. diff --git a/doc/source/admin/config-mtu.rst b/doc/source/admin/config-mtu.rst index 4207809e46..78892c7563 100644 --- a/doc/source/admin/config-mtu.rst +++ b/doc/source/admin/config-mtu.rst @@ -130,6 +130,13 @@ IPv6. IPv6 uses RA via the L3 agent because the DHCP agent only supports IPv4. Instances using IPv4 and IPv6 should obtain the same MTU value regardless of method. +.. note:: + + If you are using an MTU value on your network below 1280, please + read the warning listed in the + `IPv6 configuration guide <./config-ipv6.html#project-network-considerations>`__ + before creating any subnets. + Networks with enabled vlan transparency ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/source/admin/config-ovs-offload.rst b/doc/source/admin/config-ovs-offload.rst index ad48c921a1..c370969374 100644 --- a/doc/source/admin/config-ovs-offload.rst +++ b/doc/source/admin/config-ovs-offload.rst @@ -166,7 +166,7 @@ network and has access to the private networks of all nodes. The PCI bus number of the PF (03:00.0) and VFs (03:00.2 .. 03:00.5) will be used later. - .. code-block::bash + .. code-block:: bash # lspci | grep Ethernet 03:00.0 Ethernet controller: Mellanox Technologies MT27800 Family [ConnectX-5] @@ -176,7 +176,6 @@ network and has access to the private networks of all nodes. 03:00.4 Ethernet controller: Mellanox Technologies MT27800 Family [ConnectX-5 Virtual Function] 03:00.5 Ethernet controller: Mellanox Technologies MT27800 Family [ConnectX-5 Virtual Function] - .. code-block:: bash # ip link show enp3s0f0 diff --git a/doc/source/admin/config-qos.rst b/doc/source/admin/config-qos.rst index b5713dba79..97c7ca61d0 100644 --- a/doc/source/admin/config-qos.rst +++ b/doc/source/admin/config-qos.rst @@ -126,10 +126,11 @@ updated: Valid DSCP Marks ---------------- -Valid DSCP mark values are even numbers between 0 and 56, except 2-6, 42, 44, -and 50-54. The full list of valid DSCP marks is: +Valid DSCP mark values are even numbers between 0 and 56, except 2-6, 42, and +50-54. The full list of valid DSCP marks is: -0, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 46, 48, 56 +0, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 44, 46, +48, 56 L3 QoS support @@ -165,7 +166,7 @@ traffic directions (from the VM point of view) for **bandwidth limiting**. Rule \\ L3 service L3 router OVN L3 ==================== =================== =================== Floating IP Egress \\ Ingress Egress \\ Ingress - Gateway IP Egress \\ Ingress - + Gateway IP Egress \\ Ingress Egress \\ Ingress ==================== =================== =================== @@ -267,13 +268,12 @@ On the network and compute nodes: [agent] extensions = fip_qos, gateway_ip_qos - #. As rate limit doesn't work on Open vSwitch's ``internal`` ports, optionally, as a workaround, to make QoS bandwidth limit work on router's gateway ports, set ``ovs_use_veth`` to ``True`` in ``DEFAULT`` section in ``/etc/neutron/l3_agent.ini`` - .. code-block:: ini + .. code-block:: ini [DEFAULT] ovs_use_veth = True diff --git a/doc/source/admin/config-routed-networks.rst b/doc/source/admin/config-routed-networks.rst index ee07305c1f..9b30f322f9 100644 --- a/doc/source/admin/config-routed-networks.rst +++ b/doc/source/admin/config-routed-networks.rst @@ -634,7 +634,7 @@ creating multiple networks and/or increasing broadcast domain. example, the second segment uses the ``provider1`` physical network with VLAN ID 2020. - .. code-block:: console + .. code-block:: console $ openstack network segment create --physical-network provider1 \ --network-type vlan --segment 2020 --network multisegment1 segment1-2 diff --git a/doc/source/admin/fwaas-v2-scenario.rst b/doc/source/admin/fwaas-v2-scenario.rst index bab66ae64c..a11983bf1c 100644 --- a/doc/source/admin/fwaas-v2-scenario.rst +++ b/doc/source/admin/fwaas-v2-scenario.rst @@ -5,6 +5,37 @@ Firewall-as-a-Service (FWaaS) v2 scenario Firewall v2 has no support for OVN currently. +Installation of FWaaS v2 +------------------------ + +If possible, you should rely on packages provided by your Linux and/or +OpenStack distribution: + +* For example for Ubuntu you can install the ``neutron-fwaas-common`` + package provided by Canonical. + +.. warning:: + + Always check the version of the available package and check the releases + on https://releases.openstack.org/ + +If you use ``pip``, follow these steps to install neutron-fwaas: + +* `identify the version of the neutron-fwaas package + <https://opendev.org/openstack/releases/src/branch/master/deliverables>`_ + that matches your OpenStack version: + + * 2023.1 Antelope: latest 18.0.x version + * Zed: latest 17.0.x version + +* indicate pip to (a) install precisely this version and (b) take into + account OpenStack upper constraints on package versions for dependencies + (example for Antelope): + + .. code-block:: console + + pip install -c https://opendev.org/openstack/requirements/raw/branch/stable/2023.1/upper-constraints.txt neutron-fwaas==18.0.0 + Enable FWaaS v2 --------------- diff --git a/doc/source/admin/ovn/routed_provider_networks.rst b/doc/source/admin/ovn/routed_provider_networks.rst index 26db350635..cd534c7810 100644 --- a/doc/source/admin/ovn/routed_provider_networks.rst +++ b/doc/source/admin/ovn/routed_provider_networks.rst @@ -16,55 +16,55 @@ For example, in the OVN Northbound database, this is how a VLAN Provider Network with two segments (VLAN: 100, 200) is related to their ``Logical_Switch`` counterpart: - .. code-block:: bash +.. code-block:: bash - $ ovn-nbctl list logical_switch public - _uuid : 983719e5-4f32-4fb0-926d-46291457ca41 - acls : [] - dns_records : [] - external_ids : {"neutron:mtu"="1450", "neutron:network_name"=public, "neutron:revision_number"="3"} - forwarding_groups : [] - load_balancer : [] - name : neutron-6c8be12a-9ed0-4ac4-8130-cb8fad83cd46 - other_config : {mcast_flood_unregistered="false", mcast_snoop="true"} - ports : [81bce1ab-87f8-4ed5-8163-f16701499dfe, b23d0c2e-773b-4ecb-8306-53d117006a7b] - qos_rules : [] + $ ovn-nbctl list logical_switch public + _uuid : 983719e5-4f32-4fb0-926d-46291457ca41 + acls : [] + dns_records : [] + external_ids : {"neutron:mtu"="1450", "neutron:network_name"=public, "neutron:revision_number"="3"} + forwarding_groups : [] + load_balancer : [] + name : neutron-6c8be12a-9ed0-4ac4-8130-cb8fad83cd46 + other_config : {mcast_flood_unregistered="false", mcast_snoop="true"} + ports : [81bce1ab-87f8-4ed5-8163-f16701499dfe, b23d0c2e-773b-4ecb-8306-53d117006a7b] + qos_rules : [] - $ ovn-nbctl list logical_switch_port 81bce1ab-87f8-4ed5-8163-f16701499dfe - _uuid : 81bce1ab-87f8-4ed5-8163-f16701499dfe - addresses : [unknown] - dhcpv4_options : [] - dhcpv6_options : [] - dynamic_addresses : [] - enabled : [] - external_ids : {} - ha_chassis_group : [] - name : provnet-96f663af-19fa-4c7e-a1b8-1dfdc9cd9e82 - options : {network_name=phys-net-1} - parent_name : [] - port_security : [] - tag : 100 - tag_request : [] - type : localnet - up : false + $ ovn-nbctl list logical_switch_port 81bce1ab-87f8-4ed5-8163-f16701499dfe + _uuid : 81bce1ab-87f8-4ed5-8163-f16701499dfe + addresses : [unknown] + dhcpv4_options : [] + dhcpv6_options : [] + dynamic_addresses : [] + enabled : [] + external_ids : {} + ha_chassis_group : [] + name : provnet-96f663af-19fa-4c7e-a1b8-1dfdc9cd9e82 + options : {network_name=phys-net-1} + parent_name : [] + port_security : [] + tag : 100 + tag_request : [] + type : localnet + up : false - $ ovn-nbctl list logical_switch_port b23d0c2e-773b-4ecb-8306-53d117006a7b - _uuid : b23d0c2e-773b-4ecb-8306-53d117006a7b - addresses : [unknown] - dhcpv4_options : [] - dhcpv6_options : [] - dynamic_addresses : [] - enabled : [] - external_ids : {} - ha_chassis_group : [] - name : provnet-469cbc3d-8e06-4a8f-be3a-3fcdadfd398a - options : {network_name=phys-net-2} - parent_name : [] - port_security : [] - tag : 200 - tag_request : [] - type : localnet - up : false + $ ovn-nbctl list logical_switch_port b23d0c2e-773b-4ecb-8306-53d117006a7b + _uuid : b23d0c2e-773b-4ecb-8306-53d117006a7b + addresses : [unknown] + dhcpv4_options : [] + dhcpv6_options : [] + dynamic_addresses : [] + enabled : [] + external_ids : {} + ha_chassis_group : [] + name : provnet-469cbc3d-8e06-4a8f-be3a-3fcdadfd398a + options : {network_name=phys-net-2} + parent_name : [] + port_security : [] + tag : 200 + tag_request : [] + type : localnet + up : false As you can see, the two ``localnet`` ports are configured with a @@ -73,10 +73,10 @@ VLAN tag and are related to a single ``Logical_Switch`` entry. When node it's running on it will create a patch port to the provider bridge accordingly to the bridge mappings configuration. - .. code-block:: bash +.. code-block:: bash - compute-1: bridge-mappings = segment-1:br-provider1 - compute-2: bridge-mappings = segment-2:br-provider2 + compute-1: bridge-mappings = segment-1:br-provider1 + compute-2: bridge-mappings = segment-2:br-provider2 For example, when a port in the multisegment network gets bound to compute-1, ovn-controller will create a patch-port between br-int and diff --git a/doc/source/admin/ovn/troubleshooting.rst b/doc/source/admin/ovn/troubleshooting.rst index 646a05648c..dab9ca04c4 100644 --- a/doc/source/admin/ovn/troubleshooting.rst +++ b/doc/source/admin/ovn/troubleshooting.rst @@ -43,3 +43,78 @@ This problem is not unique to OVN but is amplified due to the possible larger size of geneve header compared to other common tunneling protocols (VXLAN). If you are using VM's as compute nodes make sure that you either lower the MTU size on the virtual interface or enable fragmentation on it. + +Duplicated or deleted OVN agents +-------------------------------- + +The "ovn-controller" process is the local controller daemon for OVN. It runs +in every host belonging to the OVN network and is in charge of registering +the host to the OVN database by creating the corresponding "Chassis" and +"Chassis_Private" registers in the Southbound database. At the same time, +when the process is gracefully stopped, it deletes both registers. These +registers are used by Neutron to control the OVN agents. + +.. code-block:: console + + $ openstack network agent list -c ID -c "Agent Type" -c Host -c Alive -c State + +--------------------------------------+------------------------------+--------+-------+-------+ + | ID | Agent Type | Host | Alive | State | + +--------------------------------------+------------------------------+--------+-------+-------+ + | a55c8d85-2071-4452-92cb-95d15c29bde7 | OVN Controller Gateway agent | u20ovn | :-) | UP | + | 62e29a01-a0ac-55c9-b4ec-e223d5c90853 | OVN Metadata agent | u20ovn | :-) | UP | + | ce9a1471-79c1-4472-adfc-9e5ce86eba07 | OVN Controller Gateway agent | u20ovn | XXX | DOWN | + | 3755938f-9aac-4f08-a1ab-32fcff56d1ce | OVN Metadata agent | u20ovn | XXX | DOWN | + +--------------------------------------+------------------------------+--------+-------+-------+ + + +If during a system upgrade the OVS "system-id" changes, the "Chassis" and +"Chassis_Private" registers will be created again but with a different UUID. +If the previous registers are not deleted (that should happen if the +"ovn-controller" process is gracefully stopped), Neutron will show duplicated +agents from the same host. In this case, only one agent will be alive and +the other one will be down because the "Chassis_Private.nb_cfg_timestamp" +is not updated. In this case, the administrator should manually delete from +the OVN Southbound database the stale registers. For example: + +* List the "Chassis" registers, filtering by hostname and name (OVS + "system-id"): + + .. code-block:: console + + $ sudo ovn-sbctl list Chassis | grep name + hostname : u20ovn + name : "a55c8d85-2071-4452-92cb-95d15c29bde7" + hostname : u20ovn + name : "ce9a1471-79c1-4472-adfc-9e5ce86eba07" + +* Delete the stale "Chassis" register: + + .. code-block:: console + + $ sudo ovn-sbctl destroy Chassis ce9a1471-79c1-4472-adfc-9e5ce86eba07 + +* List the "Chassis_Private" registers, filtering by name: + + .. code-block:: console + + $ sudo ovn-sbctl list Chassis_Private | grep name + name : "a55c8d85-2071-4452-92cb-95d15c29bde7" + name : "ce9a1471-79c1-4472-adfc-9e5ce86eba07" + +* Delete the stale "Chassis_Private" register: + + .. code-block:: console + + $ sudo ovn-sbctl destroy Chassis_Private ce9a1471-79c1-4472-adfc-9e5ce86eba07 + +If the host name is also updated during the system upgrade, the Neutron +agent list could present entries from different host names, but the older +ones will be down too. The procedure is the same. + +It could also happen that during a node decommission, the "Chassis" register +is deleted but not the "Chassis_Private" one. In that case, the OVN agent +list will present the corresponding agents with the following message: +"('Chassis' register deleted)". Again, the procedure is the same: the +administrator should manually delete the orphaned OVN Southbound database +register. Neutron will receive this event and will delete the associated +OVN agents. diff --git a/doc/source/admin/shared/deploy-selfservice-initialnetworks.txt b/doc/source/admin/shared/deploy-selfservice-initialnetworks.txt index 022bfca392..0e3f85dcfa 100644 --- a/doc/source/admin/shared/deploy-selfservice-initialnetworks.txt +++ b/doc/source/admin/shared/deploy-selfservice-initialnetworks.txt @@ -38,6 +38,13 @@ NAT for IPv4 network traffic and directly routes IPv6 network traffic. | status | ACTIVE | +-------------------------+--------------+ + .. note:: + + If you are using an MTU value on your network below 1280, please + read the warning listed in the + `IPv6 configuration guide <../config-ipv6.html#project-network-considerations>`__ + before creating any subnets. + #. Create a IPv4 subnet on the self-service network. .. code-block:: console diff --git a/doc/source/cli/index.rst b/doc/source/cli/index.rst index 59a849da9c..c530e67f02 100644 --- a/doc/source/cli/index.rst +++ b/doc/source/cli/index.rst @@ -8,6 +8,5 @@ Command-Line Interface Reference .. toctree:: :maxdepth: 1 - neutron-debug neutron-sanity-check neutron-status diff --git a/doc/source/cli/neutron-debug.rst b/doc/source/cli/neutron-debug.rst deleted file mode 100644 index d753cfeacb..0000000000 --- a/doc/source/cli/neutron-debug.rst +++ /dev/null @@ -1,309 +0,0 @@ -.. This file is manually generated, unlike many of the other chapters. - -============= -neutron-debug -============= - -The :command:`neutron-debug` client is an extension to the :command:`neutron` -command-line interface (CLI) for the OpenStack neutron-debug tool. - -This chapter documents :command:`neutron-debug` version ``2.3.0``. - -For help on a specific :command:`neutron-debug` command, enter: - -.. code-block:: console - - $ neutron-debug help COMMAND - -.. _neutron-debug_usage: - -neutron-debug usage -~~~~~~~~~~~~~~~~~~~ - -.. code-block:: console - - usage: neutron-debug [--version] [-v] [-q] [-h] [-r NUM] - [--os-service-type <os-service-type>] - [--os-endpoint-type <os-endpoint-type>] - [--service-type <service-type>] - [--endpoint-type <endpoint-type>] - [--os-auth-strategy <auth-strategy>] [--os-cloud <cloud>] - [--os-auth-url <auth-url>] - [--os-tenant-name <auth-tenant-name> | --os-project-name <auth-project-name>] - [--os-tenant-id <auth-tenant-id> | --os-project-id <auth-project-id>] - [--os-username <auth-username>] - [--os-user-id <auth-user-id>] - [--os-user-domain-id <auth-user-domain-id>] - [--os-user-domain-name <auth-user-domain-name>] - [--os-project-domain-id <auth-project-domain-id>] - [--os-project-domain-name <auth-project-domain-name>] - [--os-cert <certificate>] [--os-cacert <ca-certificate>] - [--os-key <key>] [--os-password <auth-password>] - [--os-region-name <auth-region-name>] - [--os-token <token>] [--http-timeout <seconds>] - [--os-url <url>] [--insecure] [--config-file CONFIG_FILE] - <subcommand> ... - -Subcommands ------------ - -``probe-create`` - Create probe port - create port and interface within a network namespace. - -``probe-list`` - List all probes. - -``probe-clear`` - Clear all probes. - -``probe-delete`` - Delete probe - delete port then delete the namespace. - -``probe-exec`` - Execute commands in the namespace of the probe. - -``ping-all`` - ``ping-all`` is an all-in-one command to ping all fixed IPs in a specified - network. - -.. _neutron-debug_optional: - -neutron-debug optional arguments -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -``--version`` - Show program's version number and exit - -``-v, --verbose, --debug`` - Increase verbosity of output and show tracebacks on - errors. You can repeat this option. - -``-q, --quiet`` - Suppress output except warnings and errors. - -``-h, --help`` - Show this help message and exit - -``-r NUM, --retries NUM`` - How many times the request to the Neutron server - should be retried if it fails. - -``--os-service-type <os-service-type>`` - Defaults to env[OS_NETWORK_SERVICE_TYPE] or network. - -``--os-endpoint-type <os-endpoint-type>`` - Defaults to ``env[OS_ENDPOINT_TYPE]`` or public. - -``--service-type <service-type>`` - DEPRECATED! Use --os-service-type. - -``--endpoint-type <endpoint-type>`` - DEPRECATED! Use --os-endpoint-type. - -``--os-auth-strategy <auth-strategy>`` - DEPRECATED! Only keystone is supported. - -``os-cloud <cloud>`` - Defaults to env[OS_CLOUD]. - -``--os-auth-url <auth-url>`` - Authentication URL, defaults to env[OS_AUTH_URL]. - -``--os-tenant-name <auth-tenant-name>`` - Authentication tenant name, defaults to - env[OS_TENANT_NAME]. - -``--os-project-name <auth-project-name>`` - Another way to specify tenant name. This option is - mutually exclusive with --os-tenant-name. Defaults to - env[OS_PROJECT_NAME]. - -``--os-tenant-id <auth-tenant-id>`` - Authentication tenant ID, defaults to - env[OS_TENANT_ID]. - -``--os-project-id <auth-project-id>`` - Another way to specify tenant ID. This option is - mutually exclusive with --os-tenant-id. Defaults to - env[OS_PROJECT_ID]. - -``--os-username <auth-username>`` - Authentication username, defaults to env[OS_USERNAME]. - -``--os-user-id <auth-user-id>`` - Authentication user ID (Env: OS_USER_ID) - -``--os-user-domain-id <auth-user-domain-id>`` - OpenStack user domain ID. Defaults to - env[OS_USER_DOMAIN_ID]. - -``--os-user-domain-name <auth-user-domain-name>`` - OpenStack user domain name. Defaults to - env[OS_USER_DOMAIN_NAME]. - -``--os-project-domain-id <auth-project-domain-id>`` - Defaults to env[OS_PROJECT_DOMAIN_ID]. - -``--os-project-domain-name <auth-project-domain-name>`` - Defaults to env[OS_PROJECT_DOMAIN_NAME]. - -``--os-cert <certificate>`` - Path of certificate file to use in SSL connection. - This file can optionally be prepended with the private - key. Defaults to env[OS_CERT]. - -``--os-cacert <ca-certificate>`` - Specify a CA bundle file to use in verifying a TLS - (https) server certificate. Defaults to - env[OS_CACERT]. - -``--os-key <key>`` - Path of client key to use in SSL connection. This - option is not necessary if your key is prepended to - your certificate file. Defaults to env[OS_KEY]. - -``--os-password <auth-password>`` - Authentication password, defaults to env[OS_PASSWORD]. - -``--os-region-name <auth-region-name>`` - Authentication region name, defaults to - env[OS_REGION_NAME]. - -``--os-token <token>`` - Authentication token, defaults to env[OS_TOKEN]. - -``--http-timeout <seconds>`` - Timeout in seconds to wait for an HTTP response. - Defaults to env[OS_NETWORK_TIMEOUT] or None if not - specified. - -``--os-url <url>`` - Defaults to env[OS_URL] - -``--insecure`` - Explicitly allow neutronclient to perform "insecure" - SSL (https) requests. The server's certificate will - not be verified against any certificate authorities. - This option should be used with caution. - -``--config-file CONFIG_FILE`` - Config file for interface driver (You may also use l3_agent.ini) - -neutron-debug probe-create command -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: console - - usage: neutron-debug probe-create NET - -Create probe port - create port and interface, -then place it into the created network namespace. - -Positional arguments --------------------- - -``NET ID`` - ID of the network in which the probe will be created. - -neutron-debug probe-list command -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: console - - usage: neutron-debug probe-list - -List probes. - -neutron-debug probe-clear command -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: console - - usage: neutron-debug probe-clear - -Clear all probes. - -neutron-debug probe-delete command -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: console - - usage: neutron-debug probe-delete <port-id> - -Remove a probe. - -Positional arguments --------------------- - -``<port-id>`` - ID of the probe to delete. - -neutron-debug probe-exec command -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: console - - usage: neutron-debug probe-exec <port-id> <command> - -Execute commands in the namespace of the probe - -neutron-debug ping-all command -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: console - - usage: neutron-debug ping-all <port-id> --timeout <number> - -All-in-one command to ping all fixed IPs in a specified network. -A probe creation is not needed for this command. -A new probe is created automatically. -It will, however, need to be deleted manually when it is no longer needed. -When there are multiple networks, the newly created probe will be attached -to a random network and thus the ping will take place from within that -random network. - -Positional arguments --------------------- - -``<port-id>`` - ID of the port to use. - -Optional arguments ------------------- - -``--timeout <timeout in seconds>`` - Optional ping timeout. - -neutron-debug example -~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: console - - usage: neutron-debug create-probe <NET_ID> - -Create a probe namespace within the network identified by ``NET_ID``. -The namespace will have the name of qprobe-<UUID of the probe port> - -.. note:: - - For the following examples to function, the security group rules - may need to be modified to allow the SSH (TCP port 22) or ping - (ICMP) traffic into network. - -.. code-block:: console - - usage: neutron-debug probe-exec <probe ID> "ssh <IP of instance>" - -SSH to an instance within the network. - -.. code-block:: console - - usage: neutron-debug ping-all <network ID> - -Ping all instances on this network to verify they are responding. - -.. code-block:: console - - usage: neutron-debug probe-exec <probe_ID> dhcping <VM_MAC address> -s <IP of DHCP server> - -Ping the DHCP server for this network using dhcping to verify it is working. diff --git a/doc/source/configuration/metering-agent.rst b/doc/source/configuration/metering-agent.rst index 663ec186b2..5bfa752361 100644 --- a/doc/source/configuration/metering-agent.rst +++ b/doc/source/configuration/metering-agent.rst @@ -42,18 +42,18 @@ also called as legacy) have the following format; bear in mind that if labels are shared, then the counters are for all routers of all projects where the labels were applied. - .. code-block:: json - - { - "pkts": "<the number of packets that matched the rules of the labels>", - "bytes": "<the number of bytes that matched the rules of the labels>", - "time": "<seconds between the first data collection and the last one>", - "first_update": "timeutils.utcnow_ts() of the first collection", - "last_update": "timeutils.utcnow_ts() of the last collection", - "host": "<neutron metering agent host name>", - "label_id": "<the label id>", - "tenant_id": "<the tenant id>" - } +.. code-block:: json + + { + "pkts": "<the number of packets that matched the rules of the labels>", + "bytes": "<the number of bytes that matched the rules of the labels>", + "time": "<seconds between the first data collection and the last one>", + "first_update": "timeutils.utcnow_ts() of the first collection", + "last_update": "timeutils.utcnow_ts() of the last collection", + "host": "<neutron metering agent host name>", + "label_id": "<the label id>", + "tenant_id": "<the tenant id>" + } The ``first_update`` and ``last_update`` timestamps represent the moment when the first and last data collection happened within the report interval. @@ -129,21 +129,21 @@ legacy mode such as ``bytes``, ``pkts``, ``time``, ``first_update``, ``last_update``, and ``host``. As follows we present an example of JSON message with all of the possible attributes. - .. code-block:: json - - { - "resource_id": "router-f0f745d9a59c47fdbbdd187d718f9e41-label-00c714f1-49c8-462c-8f5d-f05f21e035c7", - "project_id": "f0f745d9a59c47fdbbdd187d718f9e41", - "first_update": 1591058790, - "bytes": 0, - "label_id": "00c714f1-49c8-462c-8f5d-f05f21e035c7", - "label_name": "test1", - "last_update": 1591059037, - "host": "<hostname>", - "time": 247, - "pkts": 0, - "label_shared": true - } +.. code-block:: json + + { + "resource_id": "router-f0f745d9a59c47fdbbdd187d718f9e41-label-00c714f1-49c8-462c-8f5d-f05f21e035c7", + "project_id": "f0f745d9a59c47fdbbdd187d718f9e41", + "first_update": 1591058790, + "bytes": 0, + "label_id": "00c714f1-49c8-462c-8f5d-f05f21e035c7", + "label_name": "test1", + "last_update": 1591059037, + "host": "<hostname>", + "time": 247, + "pkts": 0, + "label_shared": true + } The ``resource_id`` is a unique identified for the "resource" being monitored. Here we consider a resource to be any of the granularities that @@ -156,4 +156,4 @@ As follows we present all of the possible configuration one can use in the metering agent init file. .. show-options:: - :config-file: etc/oslo-config-generator/metering_agent.ini
\ No newline at end of file + :config-file: etc/oslo-config-generator/metering_agent.ini diff --git a/doc/source/contributor/internals/ovn/ovn_network_logging.rst b/doc/source/contributor/internals/ovn/ovn_network_logging.rst index eca6c0c953..ff3fe8ad70 100644 --- a/doc/source/contributor/internals/ovn/ovn_network_logging.rst +++ b/doc/source/contributor/internals/ovn/ovn_network_logging.rst @@ -10,10 +10,10 @@ manage affected security group rules. Thus, there is no need for an agent. It is good to keep in mind that Openstack Security Groups (SG) and their rules (SGR) map 1:1 into OVN's Port Groups (PG) and Access Control Lists (ACL): - .. code-block:: none +.. code-block:: none - Openstack Security Group <=> OVN Port Group - Openstack Security Group Rule <=> OVN ACL + Openstack Security Group <=> OVN Port Group + Openstack Security Group Rule <=> OVN ACL Just like SGs have a list of SGRs, PGs have a list of ACLs. PGs also have a list of logical ports, but that is not really relevant in this context. @@ -50,22 +50,22 @@ https://github.com/ovn-org/ovn/commit/880dca99eaf73db7e783999c29386d03c82093bf Below is an example of a meter configuration in OVN. You can locate the fair, unit, burst_size, and rate attributes: - .. code-block:: bash +.. code-block:: bash - $ ovn-nbctl list meter - _uuid : 70c76ba9-f303-471b-9d49-25dee299827f - bands : [f114c205-a170-4425-8ca6-4e71099d1955] - external_ids : {"neutron:device_owner"=logging-plugin} - fair : true - name : acl_log_meter - unit : pktps + $ ovn-nbctl list meter + _uuid : 70c76ba9-f303-471b-9d49-25dee299827f + bands : [f114c205-a170-4425-8ca6-4e71099d1955] + external_ids : {"neutron:device_owner"=logging-plugin} + fair : true + name : acl_log_meter + unit : pktps - $ ovn-nbctl list meter-band - _uuid : f114c205-a170-4425-8ca6-4e71099d1955 - action : drop - burst_size : 25 - external_ids : {} - rate : 100 + $ ovn-nbctl list meter-band + _uuid : f114c205-a170-4425-8ca6-4e71099d1955 + action : drop + burst_size : 25 + external_ids : {} + rate : 100 The burst_size and rate attributes are configurable through neutron.conf.services.logging.log_driver_opts. That is not new. @@ -78,39 +78,39 @@ Moreover, there are a few attributes in each ACL that makes it able to provide the networking logging feature. Let's use the example below to point out the relevant fields: - .. code-block:: none - - $ openstack network log create --resource-type security_group \ - --resource ${SG} --event ACCEPT logme -f value -c ID - 2e456c7f-154e-40a8-bb10-f88ba51b90b5 - - $ openstack security group show ${SG} -f json -c rules | jq '.rules | .[2]' | grep -v 'null' - { - "id": "de4ea1e4-c946-40ed-b5b6-53c59418dc0b", - "tenant_id": "2600067ea3a446dba332d20a30ed44fa", - "security_group_id": "c604e984-0789-4c9a-a297-3e7f62fa73fd", - "ethertype": "IPv4", - "direction": "egress", - "standard_attr_id": 48, - "tags": [], - "created_at": "2021-02-06T22:17:44Z", - "updated_at": "2021-02-06T22:17:44Z", - "revision_number": 0, - "project_id": "2600067ea3a446dba332d20a30ed44fa" - } - - $ ovn-nbctl find acl \ - "external_ids:\"neutron:security_group_rule_id\""="de4ea1e4-c946-40ed-b5b6-53c59418dc0b" - _uuid : 791679e9-237d-4732-a31e-aa634496e02b - action : allow-related - direction : from-lport - external_ids : {"neutron:security_group_rule_id"="de4ea1e4-c946-40ed-b5b6-53c59418dc0b"} - log : true - match : "inport == @pg_c604e984_0789_4c9a_a297_3e7f62fa73fd && ip4" - meter : acl_log_meter - name : neutron-2e456c7f-154e-40a8-bb10-f88ba51b90b5 - priority : 1002 - severity : info +.. code-block:: none + + $ openstack network log create --resource-type security_group \ + --resource ${SG} --event ACCEPT logme -f value -c ID + 2e456c7f-154e-40a8-bb10-f88ba51b90b5 + + $ openstack security group show ${SG} -f json -c rules | jq '.rules | .[2]' | grep -v 'null' + { + "id": "de4ea1e4-c946-40ed-b5b6-53c59418dc0b", + "tenant_id": "2600067ea3a446dba332d20a30ed44fa", + "security_group_id": "c604e984-0789-4c9a-a297-3e7f62fa73fd", + "ethertype": "IPv4", + "direction": "egress", + "standard_attr_id": 48, + "tags": [], + "created_at": "2021-02-06T22:17:44Z", + "updated_at": "2021-02-06T22:17:44Z", + "revision_number": 0, + "project_id": "2600067ea3a446dba332d20a30ed44fa" + } + + $ ovn-nbctl find acl \ + "external_ids:\"neutron:security_group_rule_id\""="de4ea1e4-c946-40ed-b5b6-53c59418dc0b" + _uuid : 791679e9-237d-4732-a31e-aa634496e02b + action : allow-related + direction : from-lport + external_ids : {"neutron:security_group_rule_id"="de4ea1e4-c946-40ed-b5b6-53c59418dc0b"} + log : true + match : "inport == @pg_c604e984_0789_4c9a_a297_3e7f62fa73fd && ip4" + meter : acl_log_meter + name : neutron-2e456c7f-154e-40a8-bb10-f88ba51b90b5 + priority : 1002 + severity : info The first command creates a networking-log for a given SG. The second shows an SGR from that SG. The third shell command is where we can see how the ACL with the meter information gets populated. @@ -128,14 +128,14 @@ These are the attributes pertinent to network logging: If we poked the SGR with packets that match its criteria, the ovn-controller local to where the ACLs is enforced will log something that looks like this: - .. code-block:: none +.. code-block:: none - 2021-02-16T11:59:00.640Z|00045|acl_log(ovn_pinctrl0)|INFO| - name="neutron-2e456c7f-154e-40a8-bb10-f88ba51b90b5", - verdict=allow, severity=info: icmp,vlan_tci=0x0000,dl_src=fa:16:3e:24:dc:88, - dl_dst=fa:16:3e:15:6d:e0, - nw_src=10.0.0.12,nw_dst=10.0.0.11,nw_tos=0,nw_ecn=0,nw_ttl=64,icmp_type=8, - icmp_code=0 + 2021-02-16T11:59:00.640Z|00045|acl_log(ovn_pinctrl0)|INFO| + name="neutron-2e456c7f-154e-40a8-bb10-f88ba51b90b5", + verdict=allow, severity=info: icmp,vlan_tci=0x0000,dl_src=fa:16:3e:24:dc:88, + dl_dst=fa:16:3e:15:6d:e0, + nw_src=10.0.0.12,nw_dst=10.0.0.11,nw_tos=0,nw_ecn=0,nw_ttl=64,icmp_type=8, + icmp_code=0 It is beyond the scope of this document to talk about what happens after the logs are generated by ovn-controllers. The harvesting of files across compute nodes is something a project like diff --git a/doc/source/contributor/internals/ovn/port_forwarding.rst b/doc/source/contributor/internals/ovn/port_forwarding.rst index dd632736a0..32dc2dccc9 100644 --- a/doc/source/contributor/internals/ovn/port_forwarding.rst +++ b/doc/source/contributor/internals/ovn/port_forwarding.rst @@ -14,58 +14,58 @@ load_balancer table for all mappings for a given FIP+protocol. All PFs for the same FIP+protocol are kept as Virtual IP (VIP) mappings inside a LB entry. See the diagram below for an example of how that looks like: - .. code-block:: none - - VIP:PORT = MEMBER1:MPORT1, MEMBER2:MPORT2 - - The same is extended for port forwarding as: - - FIP:PORT = PRIVATE_IP:PRIV_PORT - - Neutron DB OVN Northbound DB - - +---------------------+ +---------------------------------+ - | Floating IP AA | | Load Balancer AA UDP | - | | | | - | +-----------------+ | | | - | | Port Forwarding | | +----------->AA:portA => internal IP1:portX | - | | | | | | | - | | External PortA +-----+ +------->AA:portB => internal IP2:portX | - | | Fixed IP1 PortX | | | | | - | | Protocol: UDP | | | +---------------------------------+ - | +-----------------+ | | - | | | +---------------------------------+ - | +-----------------+ | | | Load Balancer AA TCP | - | | Port Forwarding | | | | | - | | | | | | | - | | External PortB +---------+ +--->AA:portC => internal IP3:portX | - | | Fixed IP2 PortX | | | | | - | | Protocol: UDP | | | +---------------------------------+ - | +-----------------+ | | - | | | - | +-----------------+ | | - | | Port Forwarding | | | - | | | | | +---------------------------------+ - | | External PortC | | | | Load Balancer BB TCP | - | | Fixed IP3 PortX +-------------+ | | - | | Protocol: TCP | | | | - | +-----------------+ | +---------->BB:portD => internal IP4:portX | - | | | | | - +---------------------+ | +---------------------------------+ - | - | +-------------------+ - | | Logical Router X1 | - +---------------------+ | | | - | Floating IP BB | | | Load Balancers: | - | | | | AA UDP, AA TCP | - | +-----------------+ | | +-------------------+ - | | Port Forwarding | | | - | | | | | +-------------------+ - | | External PortD | | | | Logical Router Z1 | - | | Fixed IP4 PortX +------+ | | - | | Protocol: TCP | | | Load Balancers: | - | +-----------------+ | | BB TCP | - +---------------------+ +-------------------+ +.. code-block:: none + + VIP:PORT = MEMBER1:MPORT1, MEMBER2:MPORT2 + + The same is extended for port forwarding as: + + FIP:PORT = PRIVATE_IP:PRIV_PORT + + Neutron DB OVN Northbound DB + + +---------------------+ +---------------------------------+ + | Floating IP AA | | Load Balancer AA UDP | + | | | | + | +-----------------+ | | | + | | Port Forwarding | | +----------->AA:portA => internal IP1:portX | + | | | | | | | + | | External PortA +-----+ +------->AA:portB => internal IP2:portX | + | | Fixed IP1 PortX | | | | | + | | Protocol: UDP | | | +---------------------------------+ + | +-----------------+ | | + | | | +---------------------------------+ + | +-----------------+ | | | Load Balancer AA TCP | + | | Port Forwarding | | | | | + | | | | | | | + | | External PortB +---------+ +--->AA:portC => internal IP3:portX | + | | Fixed IP2 PortX | | | | | + | | Protocol: UDP | | | +---------------------------------+ + | +-----------------+ | | + | | | + | +-----------------+ | | + | | Port Forwarding | | | + | | | | | +---------------------------------+ + | | External PortC | | | | Load Balancer BB TCP | + | | Fixed IP3 PortX +-------------+ | | + | | Protocol: TCP | | | | + | +-----------------+ | +---------->BB:portD => internal IP4:portX | + | | | | | + +---------------------+ | +---------------------------------+ + | + | +-------------------+ + | | Logical Router X1 | + +---------------------+ | | | + | Floating IP BB | | | Load Balancers: | + | | | | AA UDP, AA TCP | + | +-----------------+ | | +-------------------+ + | | Port Forwarding | | | + | | | | | +-------------------+ + | | External PortD | | | | Logical Router Z1 | + | | Fixed IP4 PortX +------+ | | + | | Protocol: TCP | | | Load Balancers: | + | +-----------------+ | | BB TCP | + +---------------------+ +-------------------+ The OVN LB entries have names that include the id of the FIP and a protocol suffix. That protocol portion is needed because a single FIP can have multiple @@ -73,7 +73,7 @@ UDP and TCP port forwarding entries while a given LB entry can either be one or the other protocol (not both). Based on that, the format used to specify an LB entry is: - .. code-block:: ini +.. code-block:: ini pf-floatingip-<NEUTRON_FIP_ID>-<PROTOCOL> @@ -85,7 +85,7 @@ In order to differentiate a load balancer entry that was created by port forwarding vs load balancer entries maintained by ovn-octavia-provider, the external_ids field also has an owner value: - .. code-block:: python +.. code-block:: python external_ids = { ovn_const.OVN_DEVICE_OWNER_EXT_ID_KEY: PORT_FORWARDING_PLUGIN, @@ -97,7 +97,7 @@ external_ids field also has an owner value: The following registry (API) neutron events trigger the OVN backend to map port forwarding into LB: - .. code-block:: python +.. code-block:: python @registry.receives(PORT_FORWARDING_PLUGIN, [events.AFTER_INIT]) def register(self, resource, event, trigger, payload=None): diff --git a/doc/source/contributor/testing/ci_scenario_jobs.rst b/doc/source/contributor/testing/ci_scenario_jobs.rst index af81cef608..9c97c9306c 100644 --- a/doc/source/contributor/testing/ci_scenario_jobs.rst +++ b/doc/source/contributor/testing/ci_scenario_jobs.rst @@ -82,9 +82,6 @@ Below is a summary of those jobs. |tempest-integrated-networking |tempest.api (without slow tests) | 1 | Ubuntu Jammy | ovn | ovn | --- | False | False | True | Yes | | |tempest.scenario | | | | | | | | | | +----------------------------------------------+----------------------------------+-------+------------------+-------------+-----------------+----------+-------+--------+------------+-------------+ - |neutron-ovn-tempest-ovs-release-ubuntu-old |tempest.api (without slow tests) | 1 | Ubuntu Focal | ovn | ovn | --- | False | False | True | Yes | - | |tempest.scenario | | | | | | | | | | - +----------------------------------------------+----------------------------------+-------+------------------+-------------+-----------------+----------+-------+--------+------------+-------------+ |neutron-ovn-tempest-ipv6-only-ovs-release |tempest.api (without slow tests) | 1 | Ubuntu Jammy | ovn | ovn | --- | False | False | True | Yes | | |(only tests related to | | | | | | | | | | | |Neutron and Nova) | | | | | | | | | | @@ -139,11 +136,6 @@ Currently we have in that queue jobs like listed below. | |(only tests related to | | | | | | | | | | | |Neutron and Nova) | | | | | | | | | | +----------------------------------------------+----------------------------------+-------+------------------+-------------+-----------------+----------+-------+--------+------------+-------------+ - |neutron-tempest-with-uwsgi-loki |tempest.api (without slow tests) | 1 | Ubuntu Jammy | openvswitch | openvswitch | legacy | False | False | True | No | - |(non-voting) |tempest.scenario | | | | | | | | | | - | |(only tests related to | | | | | | | | | | - | |Neutron and Nova) | | | | | | | | | | - +----------------------------------------------+----------------------------------+-------+------------------+-------------+-----------------+----------+-------+--------+------------+-------------+ |neutron-ovn-tempest-ipv6-only-ovs-master |tempest.api (without slow tests) | 1 | Ubuntu Jammy | ovn | ovn | --- | False | False | True | Yes | | |(only tests related to | | | | | | | | | | | |Neutron and Nova) | | | | | | | | | | diff --git a/doc/source/install/compute-install-option2-rdo.rst b/doc/source/install/compute-install-option2-rdo.rst index d7b26398ae..e166368e59 100644 --- a/doc/source/install/compute-install-option2-rdo.rst +++ b/doc/source/install/compute-install-option2-rdo.rst @@ -24,7 +24,7 @@ networking infrastructure for instances and handles security groups. .. end Replace ``PROVIDER_INTERFACE_NAME`` with the name of the underlying - provider physical network interface. See :doc:`environment-networking-obs` + provider physical network interface. See :doc:`environment-networking-rdo` for more information. * In the ``[vxlan]`` section, configure the IP address of the physical diff --git a/doc/source/install/compute-install-option2-ubuntu.rst b/doc/source/install/compute-install-option2-ubuntu.rst index d7b26398ae..ef003646a8 100644 --- a/doc/source/install/compute-install-option2-ubuntu.rst +++ b/doc/source/install/compute-install-option2-ubuntu.rst @@ -24,8 +24,8 @@ networking infrastructure for instances and handles security groups. .. end Replace ``PROVIDER_INTERFACE_NAME`` with the name of the underlying - provider physical network interface. See :doc:`environment-networking-obs` - for more information. + provider physical network interface. + See :doc:`environment-networking-ubuntu` for more information. * In the ``[vxlan]`` section, configure the IP address of the physical network interface that handles overlay networks and enable layer-2 diff --git a/neutron/agent/common/ip_lib.py b/neutron/agent/common/ip_lib.py index 8aaa58288e..df9ca9fd94 100644 --- a/neutron/agent/common/ip_lib.py +++ b/neutron/agent/common/ip_lib.py @@ -15,6 +15,9 @@ import os +from oslo_log import log as logging + + if os.name == 'nt': from neutron.agent.windows import ip_lib from neutron.conf.agent import windows @@ -25,6 +28,12 @@ else: OPTS = linux.IP_LIB_OPTS_LINUX +if os.name == 'nt': + LOG = logging.getLogger(__name__) + LOG.warning("Support for Neutron on Windows operating systems " + "is deprecated since 2023.2 release and will be removed in " + "2024.2 OpenStack release.") + IPWrapper = ip_lib.IPWrapper IPDevice = ip_lib.IPDevice diff --git a/neutron/debug/__init__.py b/neutron/agent/l2/extensions/metadata/__init__.py index e69de29bb2..e69de29bb2 100644 --- a/neutron/debug/__init__.py +++ b/neutron/agent/l2/extensions/metadata/__init__.py diff --git a/neutron/agent/l2/extensions/metadata/host_metadata_proxy.py b/neutron/agent/l2/extensions/metadata/host_metadata_proxy.py new file mode 100644 index 0000000000..aa89782b85 --- /dev/null +++ b/neutron/agent/l2/extensions/metadata/host_metadata_proxy.py @@ -0,0 +1,200 @@ +# Copyright (c) 2022 China Unicom Cloud Data Co.,Ltd. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import grp +import io +import os +import pwd + +import jinja2 +from neutron_lib.utils import file as file_utils +from oslo_config import cfg +from oslo_log import log as logging + +from neutron._i18n import _ +from neutron.agent.linux import external_process +from neutron.agent.linux import utils +from neutron.common import metadata as common_meta +from neutron.common import utils as common_utils + +LOG = logging.getLogger(__name__) + +PROXY_SERVICE_NAME = common_meta.PROXY_SERVICE_NAME +PROXY_SERVICE_CMD = common_meta.PROXY_SERVICE_CMD + +_HOST_PATH_PROXY_TEMPLATE = jinja2.Template(""" +global + log /dev/log local0 {{ log_level }} + log-tag {{ log_tag }} + user {{ user }} + group {{ group }} + maxconn {{ maxconn }} + daemon + +frontend public + bind *:80 name clear + mode http + log global + option httplog + option dontlognull + maxconn {{ maxconn }} + timeout http-request 30s + timeout connect 30s + timeout client 32s + timeout server 32s + timeout http-keep-alive 30s + + monitor-uri /monitoruri + stats uri /admin/stats +{% for instance in instance_list %} + acl instance_{{ instance.uuid }}_{{ instance.provider_ip + }} src {{ instance.provider_ip }} +{% endfor %} + +{% for instance in instance_list %} + use_backend backend_{{ instance.uuid }}_{{ + instance.provider_ip }} if instance_{{ instance.uuid }}_{{ + instance.provider_ip }} +{% endfor %} + +{% for instance in instance_list %} +backend backend_{{ instance.uuid }}_{{ instance.provider_ip }} + mode http + balance roundrobin + retries 3 + option redispatch + timeout http-request 30s + timeout connect 30s + timeout server 30s + + http-request set-header X-Instance-ID {{ instance.uuid }} + http-request set-header X-Tenant-ID {{ instance.project_id }} + http-request set-header X-Instance-ID-Signature {{ instance.signature }} + + server metasrv {{ meta_api }} + +{% endfor %} +""") + + +class ProxyInstance(object): + def __init__(self, instance_id, provider_ip, project_id): + self.uuid = instance_id + self.provider_ip = provider_ip + self.project_id = project_id + self.signature = common_utils.sign_instance_id( + cfg.CONF.METADATA, self.uuid) + + +class HostMedataHAProxyDaemonMonitor(object): + """Manage the data and state of a host metadata haproxy process.""" + + def __init__(self, process_monitor, uuid=None, + user=None, group=None): + self._host_id = uuid or "host_metadata_proxy" + self._process_monitor = process_monitor + self.haproxy_conf = None + self.user = user or str(os.geteuid()) + self.group = group or str(os.getegid()) + + def _generate_proxy_conf(self, instance_infos): + haproxy_conf = utils.get_conf_file_name( + cfg.CONF.state_path, self._host_id, + 'haproxy.conf', True) + buf = io.StringIO() + meta_api = "%s:%s" % ( + cfg.CONF.METADATA.nova_metadata_host, + cfg.CONF.METADATA.nova_metadata_port) + + try: + username = pwd.getpwuid(int(self.user)).pw_name + except (ValueError, KeyError): + try: + username = pwd.getpwnam(self.user).pw_name + except KeyError: + raise common_meta.InvalidUserOrGroupException( + _("Invalid user/uid: '%s'") % self.user) + + try: + groupname = grp.getgrgid(int(self.group)).gr_name + except (ValueError, KeyError): + try: + groupname = grp.getgrnam(self.group).gr_name + except KeyError: + raise common_meta.InvalidUserOrGroupException( + _("Invalid group/gid: '%s'") % self.group) + + buf.write('%s' % _HOST_PATH_PROXY_TEMPLATE.render( + log_level='debug', + log_tag="%s-%s" % (PROXY_SERVICE_NAME, self._host_id), + user=username, + group=groupname, + maxconn=1024, + instance_list=instance_infos, + meta_api=meta_api)) + + contents = buf.getvalue() + LOG.debug("Host metadata haproxy config = %s", contents) + file_utils.replace_file(haproxy_conf, contents) + return haproxy_conf + + def _get_proxy_process_manager(self, callback=None): + return external_process.ProcessManager( + conf=cfg.CONF, + uuid=self._host_id, + service=PROXY_SERVICE_NAME, + default_cmd_callback=callback, + run_as_root=True) + + def _spawn_proxy(self, haproxy_conf): + def callback(pid_file): + proxy_cmd = [PROXY_SERVICE_NAME, '-f', '%s' % haproxy_conf, + '-p', '%s' % pid_file] + return proxy_cmd + + pm = self._get_proxy_process_manager(callback) + pm.enable(reload_cfg=True) + self._process_monitor.register(uuid=self._host_id, + service_name=PROXY_SERVICE_NAME, + monitored_process=pm) + LOG.debug("Host metadata proxy enabled for host %s", self._host_id) + + def config(self, instance_infos): + infos = [] + for info in instance_infos: + infos.append(ProxyInstance(info['instance_id'], + info['provider_ip'], + info['project_id'])) + if infos: + self.haproxy_conf = self._generate_proxy_conf(infos) + + def enable(self): + if self.haproxy_conf: + self._spawn_proxy(self.haproxy_conf) + return + + self.disable() + + def disable(self): + self._process_monitor.unregister(uuid=self._host_id, + service_name=PROXY_SERVICE_NAME) + pm = self._get_proxy_process_manager() + pm.disable() + utils.remove_conf_files(cfg.CONF.state_path, self._host_id) + LOG.debug("Host metadata proxy disabled for host %s", self._host_id) + + @property + def enabled(self): + return self._get_proxy_process_manager().active diff --git a/neutron/agent/linux/dhcp.py b/neutron/agent/linux/dhcp.py index 84d444c659..4f19d6cc73 100644 --- a/neutron/agent/linux/dhcp.py +++ b/neutron/agent/linux/dhcp.py @@ -41,6 +41,7 @@ from neutron.agent.linux import external_process from neutron.agent.linux import ip_lib from neutron.agent.linux import iptables_manager from neutron.cmd import runtime_checks as checks +from neutron.common import _constants as common_constants from neutron.common import utils as common_utils from neutron.ipam import utils as ipam_utils from neutron.privileged.agent.linux import dhcp as priv_dhcp @@ -1841,7 +1842,7 @@ class DeviceManager(object): if self.conf.force_metadata or self.conf.enable_isolated_metadata: ip_cidrs.append(constants.METADATA_CIDR) if netutils.is_ipv6_enabled(): - ip_cidrs.append(constants.METADATA_V6_CIDR) + ip_cidrs.append(common_constants.METADATA_V6_CIDR) self.driver.init_l3(interface_name, ip_cidrs, namespace=network.namespace) diff --git a/neutron/agent/linux/ip_lib.py b/neutron/agent/linux/ip_lib.py index 4d664381f8..9953729016 100644 --- a/neutron/agent/linux/ip_lib.py +++ b/neutron/agent/linux/ip_lib.py @@ -102,6 +102,10 @@ class AddressNotReady(exceptions.NeutronException): "become ready: %(reason)s") +class DADFailed(AddressNotReady): + pass + + InvalidArgument = privileged.InvalidArgument @@ -592,7 +596,7 @@ class IpAddrCommand(IpDeviceCommandBase): """Wait until an address is no longer marked 'tentative' or 'dadfailed' raises AddressNotReady if times out, address not present on interface - or DAD fails + raises DADFailed if Duplicate Address Detection fails """ def is_address_ready(): try: @@ -604,7 +608,7 @@ class IpAddrCommand(IpDeviceCommandBase): # Since both 'dadfailed' and 'tentative' will be set if DAD fails, # check 'dadfailed' first just to be explicit if addr_info['dadfailed']: - raise AddressNotReady( + raise DADFailed( address=address, reason=_('Duplicate address detected')) if addr_info['tentative']: return False diff --git a/neutron/agent/linux/iptables_manager.py b/neutron/agent/linux/iptables_manager.py index 3df8e8cfc4..aab8d4364b 100644 --- a/neutron/agent/linux/iptables_manager.py +++ b/neutron/agent/linux/iptables_manager.py @@ -304,7 +304,7 @@ class IptablesManager(object): # run iptables-restore without it. use_table_lock = False - # Flag to denote iptables supports --random-fully argument + # Flag to denote iptables --random-fully option enabled _random_fully = None def __init__(self, state_less=False, use_ipv6=False, nat=True, @@ -495,10 +495,11 @@ class IptablesManager(object): return self._random_fully version = self._get_version() - self.__class__._random_fully = utils.is_version_greater_equal( + + random_fully_support = utils.is_version_greater_equal( version, n_const.IPTABLES_RANDOM_FULLY_VERSION) - self._random_fully = self._random_fully and \ + self.__class__._random_fully = random_fully_support and \ cfg.CONF.AGENT.use_random_fully return self._random_fully diff --git a/neutron/agent/metadata/driver.py b/neutron/agent/metadata/driver.py index b7e69696a0..a4a62444e2 100644 --- a/neutron/agent/metadata/driver.py +++ b/neutron/agent/metadata/driver.py @@ -33,6 +33,7 @@ from neutron.agent.l3 import namespaces from neutron.agent.linux import external_process from neutron.agent.linux import ip_lib from neutron.agent.linux import utils as linux_utils +from neutron.common import _constants as common_constants from neutron.common import coordination from neutron.common import metadata as comm_meta from neutron.common import utils as common_utils @@ -241,9 +242,30 @@ class MetadataDriver(object): # HAProxy cannot bind() until IPv6 Duplicate Address Detection # completes. We must wait until the address leaves its 'tentative' # state. - ip_lib.IpAddrCommand( - parent=ip_lib.IPDevice(name=bind_interface, namespace=ns_name) - ).wait_until_address_ready(address=bind_address_v6) + try: + ip_lib.IpAddrCommand( + parent=ip_lib.IPDevice(name=bind_interface, + namespace=ns_name) + ).wait_until_address_ready(address=bind_address_v6) + except ip_lib.DADFailed as exc: + # This failure means that another DHCP agent has already + # configured this metadata address, so all requests will + # be via that single agent. + LOG.info('DAD failed for address %(address)s on interface ' + '%(interface)s in namespace %(namespace)s on network ' + '%(network)s, deleting it. Exception: %(exception)s', + {'address': bind_address_v6, + 'interface': bind_interface, + 'namespace': ns_name, + 'network': network_id, + 'exception': str(exc)}) + try: + ip_lib.delete_ip_address(bind_address_v6, bind_interface, + namespace=ns_name) + except Exception as exc: + # do not re-raise a delete failure, just log + LOG.info('Address deletion failure: %s', str(exc)) + return pm.enable() monitor.register(uuid, METADATA_SERVICE_NAME, pm) cls.monitors[router_id] = pm @@ -338,6 +360,6 @@ def apply_metadata_nat_rules(router, proxy): if netutils.is_ipv6_enabled(): for c, r in proxy.metadata_nat_rules( proxy.metadata_port, - metadata_address=(constants.METADATA_V6_IP + '/128')): + metadata_address=(common_constants.METADATA_V6_CIDR)): router.iptables_manager.ipv6['nat'].add_rule(c, r) router.iptables_manager.apply() diff --git a/neutron/agent/ovn/extensions/qos_hwol.py b/neutron/agent/ovn/extensions/qos_hwol.py index abe0783e2b..a813418d04 100644 --- a/neutron/agent/ovn/extensions/qos_hwol.py +++ b/neutron/agent/ovn/extensions/qos_hwol.py @@ -48,7 +48,7 @@ class OVSInterfaceEvent(row_event.RowEvent): def __init__(self, ovn_agent): self.ovn_agent = ovn_agent - events = (self.ROW_CREATE, self.ROW_DELETE) + events = (self.ROW_CREATE, self.ROW_UPDATE, self.ROW_DELETE) table = 'Interface' super().__init__(events, table, None) @@ -58,7 +58,7 @@ class OVSInterfaceEvent(row_event.RowEvent): return True def run(self, event, row, old): - if event == self.ROW_CREATE: + if event in (self.ROW_CREATE, self.ROW_UPDATE): self.ovn_agent.qos_hwol_ext.add_port( row.external_ids['iface-id'], row.name) elif event == self.ROW_DELETE: diff --git a/neutron/cmd/sanity/checks.py b/neutron/cmd/sanity/checks.py index b111c1c2f4..329e99463a 100644 --- a/neutron/cmd/sanity/checks.py +++ b/neutron/cmd/sanity/checks.py @@ -49,10 +49,11 @@ DNSMASQ_VERSION_HOST_ADDR6_LIST = '2.81' DIRECT_PORT_QOS_MIN_OVS_VERSION = '2.11' MINIMUM_DIBBLER_VERSION = '1.0.1' CONNTRACK_GRE_MODULE = 'nf_conntrack_proto_gre' -OVN_NB_DB_SCHEMA_GATEWAY_CHASSIS = '5.7' -OVN_NB_DB_SCHEMA_PORT_GROUP = '5.11' -OVN_NB_DB_SCHEMA_STATELESS_NAT = '5.17' -OVN_SB_DB_SCHEMA_VIRTUAL_PORT = '2.5' +OVN_NB_DB_SCHEMA_GATEWAY_CHASSIS = '5.7.0' +OVN_NB_DB_SCHEMA_PORT_GROUP = '5.11.0' +OVN_NB_DB_SCHEMA_STATELESS_NAT = '5.17.0' +OVN_SB_DB_SCHEMA_VIRTUAL_PORT = '2.5.0' +OVN_LOCALNET_LEARN_FDB = '22.09.0' class OVNCheckType(enum.Enum): @@ -63,6 +64,14 @@ class OVNCheckType(enum.Enum): def _get_ovn_version(check_type): + """Retrieves the OVN nbctl, sbctl, NS schema or SB schema version + + :param check_type: ``OVNCheckType`` enum element. This method can return + the nbctl version, the sbctl version, the NB schema + version or the SB schema version. + :return: (tuple) 3 element tuple: (major, minor, revision). (0, 0, 0) by + default. + """ if check_type in (OVNCheckType.nb_version, OVNCheckType.nb_db_schema): cmd = ['ovn-nbctl', '--version'] elif check_type in (OVNCheckType.nb_version, OVNCheckType.nb_db_schema): @@ -78,9 +87,9 @@ def _get_ovn_version(check_type): else: matched_line = re.search(r"DB Schema.*", out) - matched_version = re.search(r"(\d+\.\d+)", matched_line.group(0)) + matched_version = re.search(r"(\d+\.\d+\.\d+)", matched_line.group(0)) return versionutils.convert_version_to_tuple(matched_version.group(1) if - matched_version else '0.0') + matched_version else '0.0.0') def ovs_vxlan_supported(from_ip='192.0.2.1', to_ip='192.0.2.2'): @@ -657,3 +666,16 @@ def ovn_nb_db_schema_gateway_chassis_supported(): 'Exception: %s', e) return False return True + + +def ovn_localnet_learn_fdb_support(): + try: + ver = _get_ovn_version(OVNCheckType.nb_version) + minver = versionutils.convert_version_to_tuple(OVN_LOCALNET_LEARN_FDB) + if ver < minver: + return False + except (OSError, RuntimeError, ValueError) as e: + LOG.debug('Exception while checking OVN version. ' + 'Exception: %s', e) + return False + return True diff --git a/neutron/cmd/sanity_check.py b/neutron/cmd/sanity_check.py index 903b49db0d..8bd4318305 100644 --- a/neutron/cmd/sanity_check.py +++ b/neutron/cmd/sanity_check.py @@ -347,6 +347,14 @@ def check_ovn_nb_db_schema_gateway_chassis(): return result +def check_ovn_localnet_learn_fdb_support(): + result = checks.ovn_localnet_learn_fdb_support() + if not result: + LOG.warning('OVN does not support localnet_learn_fdb option. ' + 'This support was added in OVN 22.09.') + return result + + # Define CLI opts to test specific features, with a callback for the test OPTS = [ BoolOptCallback('ovs_vxlan', check_ovs_vxlan, default=False, @@ -431,6 +439,10 @@ OPTS = [ check_ovn_nb_db_schema_gateway_chassis, help=_('Check OVN NB DB schema support Gateway_Chassis'), default=False), + BoolOptCallback('ovn_localnet_learn_fdb_support', + check_ovn_localnet_learn_fdb_support, + help=_('Check OVN supports localnet_learn_fdb option'), + default=False), ] diff --git a/neutron/common/_constants.py b/neutron/common/_constants.py index 55fc718c49..40745ecc86 100644 --- a/neutron/common/_constants.py +++ b/neutron/common/_constants.py @@ -86,3 +86,9 @@ TRAIT_NETWORK_TUNNEL = 'CUSTOM_NETWORK_TUNNEL_PROVIDER' # The lowest binding index for L3 agents and DHCP agents. LOWEST_AGENT_BINDING_INDEX = 1 + +# Neutron-lib defines this with a /64 but it should be /128 +METADATA_V6_CIDR = constants.METADATA_V6_IP + '/128' + +# TODO(haleyb): move this constant to neutron_lib.constants +IPV4_MIN_MTU = 68 diff --git a/neutron/common/ovn/constants.py b/neutron/common/ovn/constants.py index 2a4afbf4a9..d537e2b801 100644 --- a/neutron/common/ovn/constants.py +++ b/neutron/common/ovn/constants.py @@ -32,8 +32,8 @@ OVN_ROUTER_NAME_EXT_ID_KEY = 'neutron:router_name' OVN_ROUTER_ID_EXT_ID_KEY = 'neutron:router_id' OVN_AZ_HINTS_EXT_ID_KEY = 'neutron:availability_zone_hints' OVN_ROUTER_IS_EXT_GW = 'neutron:is_ext_gw' -OVN_GW_PORT_EXT_ID_KEY = 'neutron:gw_port_id' -OVN_GW_NETWORK_EXT_ID_KEY = 'neutron:gw_network_id' +OVN_GW_PORT_EXT_ID_KEY = 'neutron:gw_port_id' # DEPRECATED, DON'T USE +OVN_GW_NETWORK_EXT_ID_KEY = 'neutron:gw_network_id' # DEPRECATED, DON'T USE OVN_SUBNET_EXT_ID_KEY = 'neutron:subnet_id' OVN_SUBNET_EXT_IDS_KEY = 'neutron:subnet_ids' OVN_SUBNET_POOL_EXT_ADDR_SCOPE4_KEY = 'neutron:subnet_pool_addr_scope4' @@ -391,6 +391,7 @@ LSP_OPTIONS_REQUESTED_CHASSIS_KEY = 'requested-chassis' LSP_OPTIONS_MCAST_FLOOD_REPORTS = 'mcast_flood_reports' LSP_OPTIONS_MCAST_FLOOD = 'mcast_flood' LSP_OPTIONS_QOS_MIN_RATE = 'qos_min_rate' +LSP_OPTIONS_LOCALNET_LEARN_FDB = 'localnet_learn_fdb' LRP_OPTIONS_RESIDE_REDIR_CH = 'reside-on-redirect-chassis' LRP_OPTIONS_REDIRECT_TYPE = 'redirect-type' @@ -434,4 +435,5 @@ OVN_SUPPORTED_VNIC_TYPES = [portbindings.VNIC_NORMAL, portbindings.VNIC_VHOST_VDPA, portbindings.VNIC_REMOTE_MANAGED, portbindings.VNIC_BAREMETAL, + portbindings.VNIC_VIRTIO_FORWARDER, ] diff --git a/neutron/conf/agent/database/agentschedulers_db.py b/neutron/conf/agent/database/agentschedulers_db.py index f58e0b2771..a46a18a262 100644 --- a/neutron/conf/agent/database/agentschedulers_db.py +++ b/neutron/conf/agent/database/agentschedulers_db.py @@ -33,7 +33,9 @@ AGENTS_SCHEDULER_OPTS = [ 'network. If this number is greater than 1, the ' 'scheduler automatically assigns multiple DHCP agents ' 'for a given tenant network, providing high ' - 'availability for the DHCP service.')), + 'availability for the DHCP service. However this does ' + 'not provide high availability for the IPv6 metadata ' + 'service in isolated networks.')), cfg.BoolOpt('enable_services_on_agents_with_admin_state_down', default=False, help=_('Enable services on an agent with admin_state_up ' diff --git a/neutron/conf/common.py b/neutron/conf/common.py index c820b3c5d7..30b09a14aa 100644 --- a/neutron/conf/common.py +++ b/neutron/conf/common.py @@ -77,7 +77,12 @@ core_opts = [ "without providing a CIDR or subnetpool ID will be " "given a CIDR via the Prefix Delegation mechanism. " "Note that enabling PD will override the behavior of " - "the default IPv6 subnetpool.")), + "the default IPv6 subnetpool."), + deprecated_for_removal=True, + deprecated_since='2023.2', + deprecated_reason=("The Dibbler client used for this feature " + "is no longer maintained. See LP#1916428"), + ), cfg.IntOpt('dhcp_lease_duration', default=86400, help=_("DHCP lease duration (in seconds). Use -1 to tell " "dnsmasq to use infinite lease times.")), diff --git a/neutron/conf/experimental.py b/neutron/conf/experimental.py index 463ab4a88b..dbb13ec820 100644 --- a/neutron/conf/experimental.py +++ b/neutron/conf/experimental.py @@ -17,11 +17,16 @@ from neutron._i18n import _ EXPERIMENTAL_CFG_GROUP = 'experimental' EXPERIMENTAL_LINUXBRIDGE = 'linuxbridge' +EXPERIMENTAL_IPV6_PD = 'ipv6_pd_enabled' experimental_opts = [ cfg.BoolOpt(EXPERIMENTAL_LINUXBRIDGE, default=False, help=_('Enable execution of the experimental Linuxbridge ' 'agent.')), + cfg.BoolOpt(EXPERIMENTAL_IPV6_PD, + default=False, + help=_('Enable execution of the experimental IPv6 Prefix ' + 'Delegation functionality in the L3 agent.')), ] diff --git a/neutron/conf/plugins/ml2/drivers/ovn/ovn_conf.py b/neutron/conf/plugins/ml2/drivers/ovn/ovn_conf.py index be75c405a8..0706477c4f 100644 --- a/neutron/conf/plugins/ml2/drivers/ovn/ovn_conf.py +++ b/neutron/conf/plugins/ml2/drivers/ovn/ovn_conf.py @@ -217,6 +217,13 @@ ovn_opts = [ 'order to disable the ``stateful-security-group`` API ' 'extension as ``allow-stateless`` keyword is only ' 'supported by OVN >= 21.06.')), + cfg.BoolOpt('localnet_learn_fdb', + default=False, + help=_('If enabled it will allow localnet ports to learn MAC ' + 'addresses and store them in FDB SB table. This avoids ' + 'flooding for traffic towards unknown IPs when port ' + 'security is disabled. It requires OVN 22.09 or ' + 'newer.')), ] @@ -330,3 +337,7 @@ def is_igmp_snooping_enabled(): def is_ovn_dhcp_disabled_for_baremetal(): return cfg.CONF.ovn.disable_ovn_dhcp_for_baremetal_ports + + +def is_learn_fdb_enabled(): + return cfg.CONF.ovn.localnet_learn_fdb diff --git a/neutron/conf/plugins/ml2/drivers/ovs_conf.py b/neutron/conf/plugins/ml2/drivers/ovs_conf.py index 7bd43dc52d..e895e0098b 100644 --- a/neutron/conf/plugins/ml2/drivers/ovs_conf.py +++ b/neutron/conf/plugins/ml2/drivers/ovs_conf.py @@ -18,6 +18,7 @@ from oslo_config import cfg from neutron._i18n import _ from neutron.conf.agent import common +from neutron.conf.agent.metadata import config as meta_conf DEFAULT_BRIDGE_MAPPINGS = [] @@ -260,6 +261,7 @@ def register_ovs_agent_opts(cfg=cfg.CONF): cfg.register_opts(dhcp_opts, "DHCP") cfg.register_opts(common.DHCP_PROTOCOL_OPTS, "DHCP") cfg.register_opts(local_ip_opts, "LOCAL_IP") + cfg.register_opts(meta_conf.METADATA_PROXY_HANDLER_OPTS, "METADATA") def register_ovs_opts(cfg=cfg.CONF): diff --git a/neutron/conf/policies/availability_zone.py b/neutron/conf/policies/availability_zone.py index 9f265dfab4..bb94f17f64 100644 --- a/neutron/conf/policies/availability_zone.py +++ b/neutron/conf/policies/availability_zone.py @@ -14,8 +14,6 @@ from neutron_lib import policy as neutron_policy from oslo_log import versionutils from oslo_policy import policy -from neutron.conf.policies import base - DEPRECATION_REASON = ( "The Availability Zone API now supports project scope and default roles.") @@ -23,7 +21,11 @@ DEPRECATION_REASON = ( rules = [ policy.DocumentedRuleDefault( name='get_availability_zone', - check_str=base.ADMIN, + # NOTE: it can't be ADMIN_OR_PROJECT_READER constant from the base + # module because that is using "project_id" in the check string and the + # availability_zone resource don't belongs to any project thus such + # check string would fail enforcement. + check_str='role:reader', description='List availability zones', operations=[ { diff --git a/neutron/conf/policies/base.py b/neutron/conf/policies/base.py index 14e419e7d1..395e4fd7f5 100644 --- a/neutron/conf/policies/base.py +++ b/neutron/conf/policies/base.py @@ -43,6 +43,20 @@ RULE_NET_OWNER = 'rule:network_owner' RULE_PARENT_OWNER = 'rule:ext_parent_owner' RULE_SG_OWNER = 'rule:sg_owner' +# In some cases we need to check owner of the parent resource, it's like that +# for example for QoS rules (check owner of QoS policy rule belongs to) or +# Floating IP port forwarding (check owner of FIP which PF is using). It's like +# that becasue those resources (QOS rules, FIP PFs) don't have project_id +# attribute at all and they belongs to the same project as parent resource (QoS +# policy, FIP). +PARENT_OWNER_MEMBER = 'role:member and ' + RULE_PARENT_OWNER +PARENT_OWNER_READER = 'role:reader and ' + RULE_PARENT_OWNER +ADMIN_OR_PARENT_OWNER_MEMBER = ( + '(' + ADMIN + ') or (' + PARENT_OWNER_MEMBER + ')') +ADMIN_OR_PARENT_OWNER_READER = ( + '(' + ADMIN + ') or (' + PARENT_OWNER_READER + ')') + + rules = [ policy.RuleDefault( 'context_is_admin', diff --git a/neutron/conf/policies/floatingip_port_forwarding.py b/neutron/conf/policies/floatingip_port_forwarding.py index 2ca8c5ce91..685cb45174 100644 --- a/neutron/conf/policies/floatingip_port_forwarding.py +++ b/neutron/conf/policies/floatingip_port_forwarding.py @@ -30,9 +30,7 @@ RESOURCE_PATH = ('/floatingips/{floatingip_id}' rules = [ policy.DocumentedRuleDefault( name='create_floatingip_port_forwarding', - check_str=neutron_policy.policy_or( - base.ADMIN_OR_PROJECT_MEMBER, - base.RULE_PARENT_OWNER), + check_str=base.ADMIN_OR_PARENT_OWNER_MEMBER, scope_types=['project'], description='Create a floating IP port forwarding', operations=[ @@ -49,9 +47,7 @@ rules = [ ), policy.DocumentedRuleDefault( name='get_floatingip_port_forwarding', - check_str=neutron_policy.policy_or( - base.ADMIN_OR_PROJECT_READER, - base.RULE_PARENT_OWNER), + check_str=base.ADMIN_OR_PARENT_OWNER_READER, scope_types=['project'], description='Get a floating IP port forwarding', operations=[ @@ -72,9 +68,7 @@ rules = [ ), policy.DocumentedRuleDefault( name='update_floatingip_port_forwarding', - check_str=neutron_policy.policy_or( - base.ADMIN_OR_PROJECT_MEMBER, - base.RULE_PARENT_OWNER), + check_str=base.ADMIN_OR_PARENT_OWNER_MEMBER, scope_types=['project'], description='Update a floating IP port forwarding', operations=[ @@ -91,9 +85,7 @@ rules = [ ), policy.DocumentedRuleDefault( name='delete_floatingip_port_forwarding', - check_str=neutron_policy.policy_or( - base.ADMIN_OR_PROJECT_MEMBER, - base.RULE_PARENT_OWNER), + check_str=base.ADMIN_OR_PARENT_OWNER_MEMBER, scope_types=['project'], description='Delete a floating IP port forwarding', operations=[ diff --git a/neutron/conf/policies/port.py b/neutron/conf/policies/port.py index 5783f080bb..bce04da941 100644 --- a/neutron/conf/policies/port.py +++ b/neutron/conf/policies/port.py @@ -270,6 +270,15 @@ rules = [ deprecated_reason=DEPRECATED_REASON, deprecated_since=versionutils.deprecated.WALLABY) ), + policy.DocumentedRuleDefault( + name='create_port:hints', + check_str=base.ADMIN, + scope_types=['project'], + description=( + 'Specify ``hints`` attribute when creating a port' + ), + operations=ACTION_POST, + ), policy.DocumentedRuleDefault( name='get_port', @@ -350,6 +359,13 @@ rules = [ deprecated_reason=DEPRECATED_REASON, deprecated_since=versionutils.deprecated.WALLABY) ), + policy.DocumentedRuleDefault( + name='get_port:hints', + check_str=base.ADMIN, + scope_types=['project'], + description='Get ``hints`` attribute of a port', + operations=ACTION_GET, + ), # TODO(amotoki): Add get_port:binding:vnic_type # TODO(amotoki): Add get_port:binding:data_plane_status @@ -592,6 +608,13 @@ rules = [ deprecated_reason=DEPRECATED_REASON, deprecated_since=versionutils.deprecated.WALLABY) ), + policy.DocumentedRuleDefault( + name='update_port:hints', + check_str=base.ADMIN, + scope_types=['project'], + description='Update ``hints`` attribute of a port', + operations=ACTION_PUT, + ), policy.DocumentedRuleDefault( name='delete_port', diff --git a/neutron/conf/policies/qos.py b/neutron/conf/policies/qos.py index c9381bab23..c507a7bdb9 100644 --- a/neutron/conf/policies/qos.py +++ b/neutron/conf/policies/qos.py @@ -104,7 +104,11 @@ rules = [ policy.DocumentedRuleDefault( name='get_rule_type', - check_str=base.ADMIN, + # NOTE(ralonsoh): it can't be ADMIN_OR_PROJECT_READER constant from the + # base module because that is using "project_id" in the check string + # and the rule type resource don't belongs to any project thus such + # check string would fail enforcement. + check_str='role:reader', scope_types=['project'], description='Get available QoS rule types', operations=[ @@ -126,7 +130,7 @@ rules = [ policy.DocumentedRuleDefault( name='get_policy_bandwidth_limit_rule', - check_str=base.ADMIN_OR_PROJECT_READER, + check_str=base.ADMIN_OR_PARENT_OWNER_READER, scope_types=['project'], description='Get a QoS bandwidth limit rule', operations=[ @@ -202,7 +206,7 @@ rules = [ policy.DocumentedRuleDefault( name='get_policy_packet_rate_limit_rule', - check_str=base.ADMIN_OR_PROJECT_READER, + check_str=base.ADMIN_OR_PARENT_OWNER_READER, scope_types=['project'], description='Get a QoS packet rate limit rule', operations=[ @@ -258,7 +262,7 @@ rules = [ policy.DocumentedRuleDefault( name='get_policy_dscp_marking_rule', - check_str=base.ADMIN_OR_PROJECT_READER, + check_str=base.ADMIN_OR_PARENT_OWNER_READER, scope_types=['project'], description='Get a QoS DSCP marking rule', operations=[ @@ -334,7 +338,7 @@ rules = [ policy.DocumentedRuleDefault( name='get_policy_minimum_bandwidth_rule', - check_str=base.ADMIN_OR_PROJECT_READER, + check_str=base.ADMIN_OR_PARENT_OWNER_READER, scope_types=['project'], description='Get a QoS minimum bandwidth rule', operations=[ @@ -409,7 +413,7 @@ rules = [ ), policy.DocumentedRuleDefault( name='get_policy_minimum_packet_rate_rule', - check_str=base.ADMIN_OR_PROJECT_READER, + check_str=base.ADMIN_OR_PARENT_OWNER_READER, scope_types=['project'], description='Get a QoS minimum packet rate rule', operations=[ @@ -464,7 +468,7 @@ rules = [ ), policy.DocumentedRuleDefault( name='get_alias_bandwidth_limit_rule', - check_str=base.ADMIN_OR_PROJECT_READER, + check_str=base.ADMIN_OR_PARENT_OWNER_READER, scope_types=['project'], description='Get a QoS bandwidth limit rule through alias', operations=[ @@ -515,7 +519,7 @@ rules = [ ), policy.DocumentedRuleDefault( name='get_alias_dscp_marking_rule', - check_str=base.ADMIN_OR_PROJECT_READER, + check_str=base.ADMIN_OR_PARENT_OWNER_READER, scope_types=['project'], description='Get a QoS DSCP marking rule through alias', operations=[ @@ -566,7 +570,7 @@ rules = [ ), policy.DocumentedRuleDefault( name='get_alias_minimum_bandwidth_rule', - check_str=base.ADMIN_OR_PROJECT_READER, + check_str=base.ADMIN_OR_PARENT_OWNER_READER, scope_types=['project'], description='Get a QoS minimum bandwidth rule through alias', operations=[ diff --git a/neutron/db/db_base_plugin_common.py b/neutron/db/db_base_plugin_common.py index fa76c9574e..dbcb201c6f 100644 --- a/neutron/db/db_base_plugin_common.py +++ b/neutron/db/db_base_plugin_common.py @@ -34,6 +34,7 @@ from oslo_log import log as logging from sqlalchemy.orm import exc from neutron.db import models_v2 +from neutron.db import rbac_db_models from neutron.objects import base as base_obj from neutron.objects import ports as port_obj from neutron.objects import subnet as subnet_obj @@ -347,7 +348,7 @@ class DbBasePluginCommon(object): # is shared to the calling tenant via an RBAC entry. matches = ('*',) + ((context.tenant_id,) if context else ()) for entry in rbac_entries: - if (entry.action == 'access_as_shared' and + if (entry.action == rbac_db_models.ACCESS_SHARED and entry.target_project in matches): return True return False diff --git a/neutron/db/db_base_plugin_v2.py b/neutron/db/db_base_plugin_v2.py index f84fb4958a..8b68a84cc2 100644 --- a/neutron/db/db_base_plugin_v2.py +++ b/neutron/db/db_base_plugin_v2.py @@ -51,13 +51,17 @@ from sqlalchemy import not_ from neutron._i18n import _ from neutron.api.rpc.agentnotifiers import l3_rpc_agent_api from neutron.common import _constants +from neutron.common import experimental from neutron.common import ipv6_utils from neutron.common import utils +from neutron.conf import experimental as c_exp from neutron.db import db_base_plugin_common from neutron.db import ipam_pluggable_backend from neutron.db import models_v2 from neutron.db import rbac_db_mixin as rbac_mixin +from neutron.db import rbac_db_models from neutron.db import standardattrdescription_db as stattr_db +from neutron.exceptions import mtu as mtu_exc from neutron.extensions import subnetpool_prefix_ops from neutron import ipam from neutron.ipam import exceptions as ipam_exc @@ -75,7 +79,7 @@ LOG = logging.getLogger(__name__) def _ensure_subnet_not_used(context, subnet_id): - models_v2.Subnet.lock_register( + models_v2.Subnet.write_lock_register( context, exc.SubnetInUse(subnet_id=subnet_id), id=subnet_id) try: registry.publish( @@ -162,7 +166,17 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, result_filters=None) return super(NeutronDbPluginV2, cls).__new__(cls, *args, **kwargs) + @staticmethod + def _validate_ipv6_pd(): + try: + if cfg.CONF.ipv6_pd_enabled: + experimental.validate_experimental_enabled( + c_exp.EXPERIMENTAL_IPV6_PD) + except cfg.NoSuchOptError: + return + def __init__(self): + self._validate_ipv6_pd() self.set_ipam_backend() if (cfg.CONF.notify_nova_on_port_status_changes or cfg.CONF.notify_nova_on_port_data_changes): @@ -210,7 +224,8 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, policy = (payload.request_body if event == events.BEFORE_CREATE else payload.latest_state) - if object_type != 'network' or policy['action'] != 'access_as_shared': + if (object_type != 'network' or + policy['action'] != rbac_db_models.ACCESS_SHARED): # we only care about shared network policies return # The object a policy targets cannot be changed so we can look @@ -253,7 +268,8 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, # any port with another RBAC entry covering it or one belonging # to the same tenant as the network owner is ok other_rbac_objs = network_obj.NetworkRBAC.get_objects( - elevated, object_id=network_id, action='access_as_shared') + elevated, object_id=network_id, + action=rbac_db_models.ACCESS_SHARED) allowed_tenants = [rbac['target_project'] for rbac in other_rbac_objs if rbac.target_project != tenant_id] @@ -265,7 +281,8 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, # allows any ports if network_obj.NetworkRBAC.get_object( elevated, object_id=network_id, - action='access_as_shared', target_project='*'): + action=rbac_db_models.ACCESS_SHARED, + target_project='*'): return ports = ports.filter(models_v2.Port.project_id == tenant_id) if ports.count(): @@ -311,7 +328,8 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, def _validate_projects_have_access_to_network(self, network, project_ids): ctx_admin = ctx.get_admin_context() other_rbac_objs = network_obj.NetworkRBAC.get_objects( - ctx_admin, object_id=network.id, action='access_as_shared') + ctx_admin, object_id=network.id, + action=rbac_db_models.ACCESS_SHARED) allowed_projects = {rbac['target_project'] for rbac in other_rbac_objs if rbac.target_project != '*'} allowed_projects.add(network.project_id) @@ -425,7 +443,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, if n['shared']: np_rbac_args = {'project_id': network.project_id, 'object_id': network.id, - 'action': 'access_as_shared', + 'action': rbac_db_models.ACCESS_SHARED, 'target_project': '*'} np_rbac_obj = network_obj.NetworkRBAC(context, **np_rbac_args) np_rbac_obj.create() @@ -443,7 +461,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, if 'shared' in n: entry = None for item in network.rbac_entries: - if (item.action == 'access_as_shared' and + if (item.action == rbac_db_models.ACCESS_SHARED and item.target_project == '*'): entry = item break @@ -453,7 +471,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, if update_shared and not entry: np_rbac_args = {'project_id': network.project_id, 'object_id': network.id, - 'action': 'access_as_shared', + 'action': rbac_db_models.ACCESS_SHARED, 'target_project': '*'} np_rbac_obj = network_obj.NetworkRBAC(context, **np_rbac_args) @@ -461,7 +479,8 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, elif not update_shared and entry: network_obj.NetworkRBAC.delete_objects( context, object_id=network.id, - action='access_as_shared', target_project='*') + action=rbac_db_models.ACCESS_SHARED, + target_project='*') # TODO(ihrachys) Below can be removed when we make sqlalchemy # event listeners in neutron_lib/db/api.py to refresh expired @@ -473,6 +492,10 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, # context. getattr(network, 'rbac_entries') + # validate 'mtu' parameter + if 'mtu' in n: + self._validate_change_network_mtu(context, id, n['mtu']) + # The filter call removes attributes from the body received from # the API that are logically tied to network resources but are # stored in other database tables handled by extensions @@ -480,6 +503,28 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, ndb_utils.filter_non_model_columns(n, models_v2.Network)) return self._make_network_dict(network, context=context) + def _validate_change_network_mtu(self, context, id, mtu): + # can support either ip_version + if mtu >= constants.IPV6_MIN_MTU: + return + + subnets = self._get_subnets_by_network(context, id) + if len(subnets) == 0: + return + + # at least one subnet present, if below IPv4 minimum we fail early + if mtu < _constants.IPV4_MIN_MTU: + raise mtu_exc.NetworkMTUSubnetConflict( + net_id=id, mtu=_constants.IPV4_MIN_MTU) + + # We do not need to check IPv4 subnets as they will have been + # caught by above IPV4_MIN_MTU check + for subnet in subnets: + if (subnet.ip_version == constants.IP_VERSION_6 and + mtu < constants.IPV6_MIN_MTU): + raise mtu_exc.NetworkMTUSubnetConflict( + net_id=id, mtu=constants.IPV6_MIN_MTU) + def _ensure_network_not_in_use(self, context, net_id): non_auto_ports = context.session.query( models_v2.Port.id).filter_by(network_id=net_id).filter( @@ -722,6 +767,23 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, "Prefix Delegation.") raise exc.BadRequest(resource='subnets', msg=reason) + def _validate_subnet_network_mtu(self, network, subnet): + """Validates that network mtu is correct for subnet association""" + mtu = network.mtu + if not mtu or mtu >= constants.IPV6_MIN_MTU: + return + + # if below IPv4 minimum we fail early + if mtu < _constants.IPV4_MIN_MTU: + raise mtu_exc.NetworkMTUSubnetConflict(net_id=network.id, mtu=mtu) + + # We do not need to check IPv4 subnets as they will have been + # caught by above IPV4_MIN_MTU check + ip_version = subnet.get('ip_version') + if (ip_version == constants.IP_VERSION_6 and + mtu < constants.IPV6_MIN_MTU): + raise mtu_exc.NetworkMTUSubnetConflict(net_id=network.id, mtu=mtu) + def _update_router_gw_ports(self, context, network, subnet): l3plugin = directory.get_plugin(plugin_constants.L3) if l3plugin: @@ -883,6 +945,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, with db_api.CONTEXT_WRITER.using(context): network = self._get_network(context, subnet['subnet']['network_id']) + self._validate_subnet_network_mtu(network, s) subnet, ipam_subnet = self.ipam.allocate_subnet(context, network, subnet['subnet'], diff --git a/neutron/db/external_net_db.py b/neutron/db/external_net_db.py index ef286c61e3..fb6c3c9d90 100644 --- a/neutron/db/external_net_db.py +++ b/neutron/db/external_net_db.py @@ -31,6 +31,7 @@ from sqlalchemy.sql import expression as expr from neutron._i18n import _ from neutron.db import models_v2 +from neutron.db import rbac_db_models from neutron.extensions import rbac as rbac_ext from neutron.objects import network as net_obj from neutron.objects import ports as port_obj @@ -47,7 +48,7 @@ def _network_filter_hook(context, original_model, conditions): # shared check so we don't need to worry about ensuring that rbac_model = original_model.rbac_entries.property.mapper.class_ tenant_allowed = ( - (rbac_model.action == 'access_as_external') & + (rbac_model.action == rbac_db_models.ACCESS_EXTERNAL) & (rbac_model.target_project == context.tenant_id) | (rbac_model.target_project == '*')) conditions = expr.or_(tenant_allowed, *conditions) @@ -102,7 +103,7 @@ class External_net_db_mixin(object): context, network_id=net_data['id']).create() net_rbac_args = {'project_id': net_data['tenant_id'], 'object_id': net_data['id'], - 'action': 'access_as_external', + 'action': rbac_db_models.ACCESS_EXTERNAL, 'target_project': '*'} net_obj.NetworkRBAC(context, **net_rbac_args).create() net_data[extnet_apidef.EXTERNAL] = external @@ -123,7 +124,7 @@ class External_net_db_mixin(object): if allow_all: net_rbac_args = {'project_id': net_data['tenant_id'], 'object_id': net_id, - 'action': 'access_as_external', + 'action': rbac_db_models.ACCESS_EXTERNAL, 'target_project': '*'} net_obj.NetworkRBAC(context, **net_rbac_args).create() else: @@ -138,7 +139,8 @@ class External_net_db_mixin(object): net_obj.ExternalNetwork.delete_objects( context, network_id=net_id) net_obj.NetworkRBAC.delete_objects( - context, object_id=net_id, action='access_as_external') + context, object_id=net_id, + action=rbac_db_models.ACCESS_EXTERNAL) net_data[extnet_apidef.EXTERNAL] = False def _process_l3_delete(self, context, network_id): @@ -154,7 +156,7 @@ class External_net_db_mixin(object): context = payload.context if (object_type != 'network' or - policy['action'] != 'access_as_external'): + policy['action'] != rbac_db_models.ACCESS_EXTERNAL): return net = self.get_network(context, policy['object_id']) if not context.is_admin and net['tenant_id'] != context.tenant_id: @@ -175,12 +177,12 @@ class External_net_db_mixin(object): context = payload.context if (object_type != 'network' or - policy['action'] != 'access_as_external'): + policy['action'] != rbac_db_models.ACCESS_EXTERNAL): return # If the network still have rbac policies, we should not # update external attribute. if net_obj.NetworkRBAC.count(context, object_id=policy['object_id'], - action='access_as_external'): + action=rbac_db_models.ACCESS_EXTERNAL): return net = self.get_network(context, policy['object_id']) self._process_l3_update(context, net, @@ -195,7 +197,7 @@ class External_net_db_mixin(object): context = payload.context if (object_type != 'network' or - policy['action'] != 'access_as_external'): + policy['action'] != rbac_db_models.ACCESS_EXTERNAL): return new_project = None if event == events.BEFORE_UPDATE: @@ -215,7 +217,7 @@ class External_net_db_mixin(object): # router lookup because they will have access either way if net_obj.NetworkRBAC.count( context, object_id=policy['object_id'], - action='access_as_external', target_project='*'): + action=rbac_db_models.ACCESS_EXTERNAL, target_project='*'): return router_exist = l3_obj.Router.objects_exist(context, **filters) else: @@ -230,7 +232,7 @@ class External_net_db_mixin(object): details=msg) projects = net_obj.NetworkRBAC.get_projects( context, object_id=policy['object_id'], - action='access_as_external') + action=rbac_db_models.ACCESS_EXTERNAL) projects_with_entries = [project for project in projects if project != '*'] if new_project: diff --git a/neutron/db/ipam_backend_mixin.py b/neutron/db/ipam_backend_mixin.py index e734996900..9c245ae689 100644 --- a/neutron/db/ipam_backend_mixin.py +++ b/neutron/db/ipam_backend_mixin.py @@ -683,7 +683,7 @@ class IpamBackendMixin(db_base_plugin_common.DbBasePluginCommon): msg = ('This subnet is being modified by another concurrent ' 'operation') for subnet in subnets: - subnet.lock_register( + subnet.read_lock_register( context, exc.SubnetInUse(subnet_id=subnet.id, reason=msg), id=subnet.id) subnet_dicts = [self._make_subnet_dict(subnet, context=context) diff --git a/neutron/db/l3_db.py b/neutron/db/l3_db.py index 081881f005..dd1e8ee28b 100644 --- a/neutron/db/l3_db.py +++ b/neutron/db/l3_db.py @@ -53,6 +53,7 @@ from neutron.db import l3_attrs_db from neutron.db.models import l3 as l3_models from neutron.db.models import l3_attrs as l3_attrs_models from neutron.db import models_v2 +from neutron.db import rbac_db_models from neutron.db import standardattrdescription_db as st_attr from neutron.extensions import l3 from neutron.extensions import segment as segment_ext @@ -884,7 +885,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, with db_api.CONTEXT_READER.using(elevated): rbac_allowed_projects = network_obj.NetworkRBAC.get_projects( elevated, object_id=subnet['network_id'], - action='access_as_shared', + action=rbac_db_models.ACCESS_SHARED, target_project=context.project_id) # Fail if the current project_id is NOT in the allowed diff --git a/neutron/db/migration/alembic_migrations/env.py b/neutron/db/migration/alembic_migrations/env.py index dee4f9c474..921e1c5671 100644 --- a/neutron/db/migration/alembic_migrations/env.py +++ b/neutron/db/migration/alembic_migrations/env.py @@ -13,14 +13,16 @@ # under the License. from alembic import context +from neutron_lib import context as n_context +from neutron_lib.db import api as db_api from neutron_lib.db import model_base from oslo_config import cfg +from oslo_db import options as db_options import sqlalchemy as sa from sqlalchemy import event # noqa from neutron.db.migration.alembic_migrations import external from neutron.db.migration import autogen -from neutron.db.migration.connection import DBConnection from neutron.db.migration.models import head # noqa try: @@ -53,6 +55,13 @@ def set_mysql_engine(): model_base.BASEV2.__table_args__['mysql_engine']) +def setup_conf(): + conf = cfg.CONF + conf.register_opts(db_options.database_opts, 'database') + conf.set_override('connection', neutron_config.database.connection, + group='database') + + def include_object(object_, name, type_, reflected, compare_to): if type_ == 'table' and name in external.TABLES: return False @@ -101,11 +110,12 @@ def run_migrations_online(): and associate a connection with the context. """ + setup_conf() set_mysql_engine() - connection = config.attributes.get('connection') - with DBConnection(neutron_config.database.connection, connection) as conn: + admin_ctx = n_context.get_admin_context() + with db_api.CONTEXT_WRITER.using(admin_ctx) as session: context.configure( - connection=conn, + connection=session.connection(), target_metadata=target_metadata, include_object=include_object, process_revision_directives=autogen.process_revision_directives diff --git a/neutron/db/migration/alembic_migrations/versions/2023.2/expand/6f1145bff34c_port_hints.py b/neutron/db/migration/alembic_migrations/versions/2023.2/expand/6f1145bff34c_port_hints.py new file mode 100644 index 0000000000..b82d3de956 --- /dev/null +++ b/neutron/db/migration/alembic_migrations/versions/2023.2/expand/6f1145bff34c_port_hints.py @@ -0,0 +1,45 @@ +# Copyright 2023 OpenStack Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +from alembic import op +from neutron_lib.db import constants as db_const +import sqlalchemy as sa + + +"""port_hints + +Revision ID: 6f1145bff34c +Revises: 93f394357a27 +Create Date: 2023-01-01 00:00:00.000000 + +""" + +# revision identifiers, used by Alembic. +revision = '6f1145bff34c' +down_revision = '93f394357a27' + + +def upgrade(): + op.create_table( + 'porthints', + sa.Column( + 'port_id', + sa.String(length=db_const.UUID_FIELD_SIZE), + sa.ForeignKey('ports.id', ondelete='CASCADE'), + primary_key=True), + sa.Column('hints', + sa.String(4095), + nullable=False), + ) diff --git a/neutron/db/migration/alembic_migrations/versions/2023.2/expand/93f394357a27_remove_in_use_on_subnets.py b/neutron/db/migration/alembic_migrations/versions/2023.2/expand/93f394357a27_remove_in_use_on_subnets.py new file mode 100644 index 0000000000..0e9ceb6071 --- /dev/null +++ b/neutron/db/migration/alembic_migrations/versions/2023.2/expand/93f394357a27_remove_in_use_on_subnets.py @@ -0,0 +1,42 @@ +# Copyright 2023 OpenStack Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +from alembic import op +import sqlalchemy as sa + + +"""remove in_use from subnet + +Revision ID: 93f394357a27 +Revises: fc153938cdc1 +Create Date: 2023-03-07 14:48:15.763633 + +""" + +# revision identifiers, used by Alembic. +revision = '93f394357a27' +down_revision = 'fc153938cdc1' + + +def upgrade(): + op.drop_column('subnets', 'in_use') + + +def expand_drop_exceptions(): + """Support dropping 'in_use' column in table 'subnets'""" + + return { + sa.Column: ['subnets.in_use'] + } diff --git a/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD b/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD index 961bd474e5..8e31a8bd56 100644 --- a/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD +++ b/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD @@ -1 +1 @@ -fc153938cdc1 +6f1145bff34c diff --git a/neutron/db/models/port_hints.py b/neutron/db/models/port_hints.py new file mode 100644 index 0000000000..8ef171bba5 --- /dev/null +++ b/neutron/db/models/port_hints.py @@ -0,0 +1,35 @@ +# Copyright 2023 Ericsson Software Technology +# +# 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. + +from neutron_lib.db import constants as db_const +from neutron_lib.db import model_base +import sqlalchemy as sa + +from neutron.db import models_v2 + + +class PortHints(model_base.BASEV2): + __tablename__ = 'porthints' + port_id = sa.Column( + sa.String(db_const.UUID_FIELD_SIZE), + sa.ForeignKey('ports.id', ondelete='CASCADE'), + primary_key=True) + hints = sa.Column('hints', sa.String(length=4095), nullable=False) + port = sa.orm.relationship( + models_v2.Port, + load_on_pending=True, + backref=sa.orm.backref( + 'hints', uselist=False, cascade='delete', lazy='subquery')) + + revises_on_change = ('port', ) diff --git a/neutron/db/models_v2.py b/neutron/db/models_v2.py index 9a03b46763..8ab9707b17 100644 --- a/neutron/db/models_v2.py +++ b/neutron/db/models_v2.py @@ -33,25 +33,47 @@ from neutron.db import rbac_db_models class HasInUse(object): """NeutronBaseV2 mixin, to add the flag "in_use" to a DB model. - The content of this flag (boolean) parameter is not relevant. The goal of - this field is to be used in a write transaction to mark a DB register as - "in_use". Writing any value on this DB parameter will lock the container - register. At the end of the DB transaction, the DB engine will check if - this register was modified or deleted. In such case, the transaction will - fail and won't be committed. - - "lock_register" is the method to write the register "in_use" column. - Because the lifespan of this DB lock is the DB transaction, there isn't an - unlock method. The lock will finish once the transaction ends. + The goal of this class is to allow users lock specific database rows with + a shared or exclusive lock (without necessarily introducing a change in + the table itself). Having these locks allows the DB engine to prevent + concurrent modifications (e.g. the deletion of a resource while we are + currently adding a new dependency on the resource). + + "read_lock_register" takes a shared DB lock on the row specified by the + filters. The lock is automatically released once the transaction ends. + You can have any number of parallel read locks on the same DB row. But + you can not have any write lock in parallel. + + "write_lock_register" takes an exclusive DB lock on the row specified by + the filters. The lock is automatically released on transaction commit. + You may only have one write lock on each row at a time. It therefor + blocks all other read and write locks to this row. """ - in_use = sa.Column(sa.Boolean(), nullable=False, - server_default=sql.false(), default=False) @classmethod - def lock_register(cls, context, exception, **filters): + def write_lock_register(cls, context, exception, **filters): + # we use `with_for_update()` to include `FOR UPDATE` in the sql + # statement. + # we need to set `enable_eagerloads(False)` so that we do not try to + # load attached resources (e.g. standardattributes) as this breaks the + # `FOR UPDATE` statement. num_reg = context.session.query( - cls).filter_by(**filters).update({'in_use': True}) - if num_reg != 1: + cls).filter_by(**filters).enable_eagerloads( + False).with_for_update().first() + if num_reg is None: + raise exception + + @classmethod + def read_lock_register(cls, context, exception, **filters): + # we use `with_for_update(read=True)` to include `LOCK IN SHARE MODE` + # in the sql statement. + # we need to set `enable_eagerloads(False)` so that we do not try to + # load attached resources (e.g. standardattributes) as this breaks the + # `LOCK IN SHARE MODE` statement. + num_reg = context.session.query( + cls).filter_by(**filters).enable_eagerloads( + False).with_for_update(read=True).first() + if num_reg is None: raise exception diff --git a/neutron/db/port_hints_db.py b/neutron/db/port_hints_db.py new file mode 100644 index 0000000000..0b45b413fb --- /dev/null +++ b/neutron/db/port_hints_db.py @@ -0,0 +1,53 @@ +# Copyright 2023 Ericsson Software Technology +# +# 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. + +from neutron_lib.api.definitions import port_hints as phints_def +from oslo_serialization import jsonutils + +from neutron.objects.port.extensions import port_hints as phints_obj + + +class PortHintsMixin(object): + """Mixin class to add hints to a port""" + + def _process_create_port(self, context, data, result): + if not data.get(phints_def.HINTS): + result[phints_def.HINTS] = None + return + + obj = phints_obj.PortHints( + context, port_id=result['id'], + hints=data[phints_def.HINTS]) + obj.create() + result[phints_def.HINTS] = data[phints_def.HINTS] + + def _process_update_port(self, context, data, result): + obj = phints_obj.PortHints.get_object( + context, port_id=result['id']) + + if obj: + if data[phints_def.HINTS]: + obj.hints = data[phints_def.HINTS] + obj.update() + else: + obj.delete() + result[phints_def.HINTS] = data[phints_def.HINTS] + else: + self._process_create_port(context, data, result) + + def _extend_port_dict(self, port_db, result): + if port_db.hints: + result[phints_def.HINTS] = jsonutils.loads(port_db.hints.hints) + else: + result[phints_def.HINTS] = None diff --git a/neutron/db/securitygroups_db.py b/neutron/db/securitygroups_db.py index f65b1d8fc3..57cf316ee0 100644 --- a/neutron/db/securitygroups_db.py +++ b/neutron/db/securitygroups_db.py @@ -251,6 +251,12 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase, if sg['name'] == 'default' and not context.is_admin: raise ext_sg.SecurityGroupCannotRemoveDefault() + # Check if there are rules with remote_group_id ponting to + # the security_group to be deleted + rules_ids_as_remote = self._get_security_group_rules_by_remote( + context=context, remote_id=id, + ) + self._registry_publish(resources.SECURITY_GROUP, events.BEFORE_DELETE, exc_cls=ext_sg.SecurityGroupInUse, id=id, @@ -279,6 +285,20 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase, context, resource_id=id, states=(sec_group,), metadata={'security_group_rule_ids': sgr_ids, 'name': sg['name']})) + for rule in rules_ids_as_remote: + registry.publish( + resources.SECURITY_GROUP_RULE, + events.AFTER_DELETE, + self, + payload=events.DBEventPayload( + context, + resource_id=rule['id'], + metadata={'security_group_id': rule['security_group_id'], + 'remote_group_id': rule['remote_group_id'], + 'rule': rule + } + ) + ) @db_api.retry_if_session_inactive() def update_security_group(self, context, id, security_group): @@ -365,6 +385,23 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase, self._make_security_group_binding_dict, filters=filters, fields=fields) + def _get_security_group_rules_by_remote(self, context, remote_id): + return model_query.get_collection( + context, sg_models.SecurityGroupRule, + self._make_security_group_rule_dict, + filters={'remote_group_id': [remote_id]}, + fields=['id', + 'remote_group_id', + 'security_group_id', + 'direction', + 'ethertype', + 'protocol', + 'port_range_min', + 'port_range_max', + 'normalized_cidr' + ] + ) + @db_api.retry_if_session_inactive() def _delete_port_security_group_bindings(self, context, port_id): with db_api.CONTEXT_WRITER.using(context): diff --git a/neutron/debug/README b/neutron/debug/README deleted file mode 100644 index f5ce9a1271..0000000000 --- a/neutron/debug/README +++ /dev/null @@ -1,38 +0,0 @@ -Debug Helper Script for Neutron - -- Configure -export NEUTRON_TEST_CONFIG_FILE=/etc/neutron/debug.ini -or -export NEUTRON_TEST_CONFIG_FILE=/etc/neutron/l3_agent.ini - -you can also specify config file by --config-file option - -- Usage -neutron-debug commands - -probe-create <net-id> - Create probe port - create port and interface, then plug it in. - This commands returns a port id of a probe port. A probe port is a port which is used to test. - The port id is probe id. - We can have multiple probe probes in a network, in order to check connectivity between ports. - - neutron-debug probe-exec probe_id_1 'nc -l 192.168.100.3 22' - neutron-debug probe-exec probe_id_2 'nc -vz 192.168.100.4 22' - - Note: You should use a user and a tenant who has permission to - modify network and subnet if you want to probe. For example, you need to be admin user if you - want to probe external network. - -probe-delete <port-id> Delete probe - delete port then unplug -probe-exec <port-id> 'command' Exec commands on the namespace of the probe -`probe-exec <port-id>` 'interactive command' Exec interactive command (eg, ssh) - -probe-list List probes -probe-clear Clear All probes - -ping-all --id <network_id> --timeout 1 (optional) - ping-all is all-in-one command to ping all fixed ip's in all network or a specified network. - In the command probe is automatically created if needed. - -neutron-debug extends the shell of neutronclient, so you can use all the commands of neutron - diff --git a/neutron/debug/commands.py b/neutron/debug/commands.py deleted file mode 100644 index 35fa34c079..0000000000 --- a/neutron/debug/commands.py +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright 2012, Nachi Ueno, NTT MCL, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cliff import lister -from neutronclient.common import utils -from neutronclient.neutron import v2_0 as client -from neutronclient.neutron.v2_0 import port - -from neutron._i18n import _ - - -class ProbeCommand(client.NeutronCommand): - - def get_debug_agent(self): - return self.app.debug_agent - - -class CreateProbe(ProbeCommand): - """Create probe port and interface, then plug it in.""" - - def get_parser(self, prog_name): - parser = super(CreateProbe, self).get_parser(prog_name) - parser.add_argument( - 'id', metavar='network_id', - help=_('ID of network to probe')) - parser.add_argument( - '--device-owner', - default='network', choices=['network', 'compute'], - help=_('Owner type of the device: network/compute')) - return parser - - def take_action(self, parsed_args): - debug_agent = self.get_debug_agent() - probe_port = debug_agent.create_probe(parsed_args.id, - parsed_args.device_owner) - self.log.info(_('Probe created : %s '), probe_port.id) - - -class DeleteProbe(ProbeCommand): - """Delete probe - delete port then uplug.""" - - def get_parser(self, prog_name): - parser = super(DeleteProbe, self).get_parser(prog_name) - parser.add_argument( - 'id', metavar='port_id', - help=_('ID of probe port to delete')) - return parser - - def take_action(self, parsed_args): - debug_agent = self.get_debug_agent() - debug_agent.delete_probe(parsed_args.id) - self.log.info(_('Probe %s deleted'), parsed_args.id) - - -class ListProbe(ProbeCommand, lister.Lister): - """List probes.""" - - _formatters = {'fixed_ips': port._format_fixed_ips, } - - def take_action(self, parsed_args): - debug_agent = self.get_debug_agent() - info = debug_agent.list_probes() - columns = sorted(info[0].keys()) if info else [] - return (columns, (utils.get_item_properties( - s, columns, formatters=self._formatters, ) - for s in info), ) - - -class ClearProbe(ProbeCommand): - """Clear All probes.""" - - def take_action(self, parsed_args): - debug_agent = self.get_debug_agent() - cleared_probes_count = debug_agent.clear_probes() - self.log.info('%d probe(s) deleted', cleared_probes_count) - - -class ExecProbe(ProbeCommand): - """Exec commands on the namespace of the probe.""" - - def get_parser(self, prog_name): - parser = super(ExecProbe, self).get_parser(prog_name) - parser.add_argument( - 'id', metavar='port_id', - help=_('ID of probe port to execute command')) - parser.add_argument( - 'command', metavar='command', - nargs='?', - default=None, - help=_('Command to execute')) - return parser - - def take_action(self, parsed_args): - debug_agent = self.get_debug_agent() - result = debug_agent.exec_command(parsed_args.id, parsed_args.command) - self.app.stdout.write(result + '\n') - - -class PingAll(ProbeCommand): - """Ping all fixed_ip.""" - - def get_parser(self, prog_name): - parser = super(PingAll, self).get_parser(prog_name) - parser.add_argument( - '--timeout', metavar='<timeout>', - default=10, - help=_('Ping timeout')) - parser.add_argument( - '--id', metavar='network_id', - default=None, - help=_('ID of network')) - return parser - - def take_action(self, parsed_args): - debug_agent = self.get_debug_agent() - result = debug_agent.ping_all(parsed_args.id, - timeout=parsed_args.timeout) - self.app.stdout.write(result + '\n') diff --git a/neutron/debug/debug_agent.py b/neutron/debug/debug_agent.py deleted file mode 100644 index 5fbc6d2f2f..0000000000 --- a/neutron/debug/debug_agent.py +++ /dev/null @@ -1,176 +0,0 @@ -# Copyright 2012, Nachi Ueno, NTT MCL, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import shlex -import socket - -import netaddr -from neutron_lib.api.definitions import portbindings -from neutron_lib import constants -from oslo_log import log as logging - -from neutron.agent.linux import dhcp -from neutron.agent.linux import ip_lib - -LOG = logging.getLogger(__name__) - -DEVICE_OWNER_NETWORK_PROBE = constants.DEVICE_OWNER_NETWORK_PREFIX + 'probe' - -DEVICE_OWNER_COMPUTE_PROBE = constants.DEVICE_OWNER_COMPUTE_PREFIX + 'probe' - - -class NeutronDebugAgent(object): - - def __init__(self, conf, client, driver): - self.conf = conf - self.client = client - self.driver = driver - - def _get_namespace(self, port): - return "qprobe-%s" % port.id - - def create_probe(self, network_id, device_owner='network'): - network = self._get_network(network_id) - - port = self._create_port(network, device_owner) - interface_name = self.driver.get_device_name(port) - namespace = self._get_namespace(port) - - if ip_lib.device_exists(interface_name, namespace=namespace): - LOG.debug('Reusing existing device: %s.', interface_name) - else: - self.driver.plug(network.id, - port.id, - interface_name, - port.mac_address, - namespace=namespace) - ip_cidrs = [] - for fixed_ip in port.fixed_ips: - subnet = fixed_ip.subnet - net = netaddr.IPNetwork(subnet.cidr) - ip_cidr = '%s/%s' % (fixed_ip.ip_address, net.prefixlen) - ip_cidrs.append(ip_cidr) - self.driver.init_l3(interface_name, ip_cidrs, namespace=namespace) - return port - - def _get_subnet(self, subnet_id): - subnet_dict = self.client.show_subnet(subnet_id)['subnet'] - return dhcp.DictModel(subnet_dict) - - def _get_network(self, network_id): - network_dict = self.client.show_network(network_id)['network'] - network = dhcp.DictModel(network_dict) - # pylint: disable=assigning-non-slot - network.external = network_dict.get('router:external') - obj_subnet = [self._get_subnet(s_id) for s_id in network.subnets] - network.subnets = obj_subnet - return network - - def clear_probes(self): - """Returns number of deleted probes""" - ports = self.client.list_ports( - device_id=socket.gethostname(), - device_owner=[DEVICE_OWNER_NETWORK_PROBE, - DEVICE_OWNER_COMPUTE_PROBE]) - info = ports['ports'] - for port in info: - self.delete_probe(port['id']) - return len(info) - - def delete_probe(self, port_id): - port = dhcp.DictModel(self.client.show_port(port_id)['port']) - namespace = self._get_namespace(port) - if ip_lib.network_namespace_exists(namespace): - self.driver.unplug(self.driver.get_device_name(port), - namespace=namespace) - try: - ip_lib.delete_network_namespace(namespace) - except Exception: - LOG.warning('Failed to delete namespace %s', namespace) - else: - self.driver.unplug(self.driver.get_device_name(port)) - self.client.delete_port(port.id) - - def list_probes(self): - ports = self.client.list_ports( - device_owner=[DEVICE_OWNER_NETWORK_PROBE, - DEVICE_OWNER_COMPUTE_PROBE]) - info = ports['ports'] - for port in info: - port['device_name'] = self.driver.get_device_name( - dhcp.DictModel(port)) - return info - - def exec_command(self, port_id, command=None): - port = dhcp.DictModel(self.client.show_port(port_id)['port']) - ip = ip_lib.IPWrapper() - namespace = self._get_namespace(port) - if not command: - return "sudo ip netns exec %s" % self._get_namespace(port) - namespace = ip.ensure_namespace(namespace) - # NOTE(ralonsoh): this is going to be called from inside the - # "neutron-debug" shell command; privsep is not configured. - return namespace.netns.execute(shlex.split(command)) - - def ensure_probe(self, network_id): - ports = self.client.list_ports(network_id=network_id, - device_id=socket.gethostname(), - device_owner=DEVICE_OWNER_NETWORK_PROBE) - info = ports.get('ports', []) - if info: - return dhcp.DictModel(info[0]) - else: - return self.create_probe(network_id) - - def ping_all(self, network_id=None, timeout=1): - if network_id: - ports = self.client.list_ports(network_id=network_id)['ports'] - else: - ports = self.client.list_ports()['ports'] - result = "" - for port in ports: - probe = self.ensure_probe(port['network_id']) - if port['device_owner'] == DEVICE_OWNER_NETWORK_PROBE: - continue - for fixed_ip in port['fixed_ips']: - address = fixed_ip['ip_address'] - subnet = self._get_subnet(fixed_ip['subnet_id']) - if subnet.ip_version == 4: - ping_command = 'ping' - else: - ping_command = 'ping6' - result += self.exec_command(probe.id, - '%s -c 1 -w %s %s' % (ping_command, - timeout, - address)) - return result - - def _create_port(self, network, device_owner): - host = self.conf.host - body = {'port': {'admin_state_up': True, - 'network_id': network.id, - 'device_id': '%s' % socket.gethostname(), - 'device_owner': '%s:probe' % device_owner, - 'tenant_id': network.tenant_id, - portbindings.HOST_ID: host, - 'fixed_ips': [dict(subnet_id=s.id) - for s in network.subnets]}} - port_dict = self.client.create_port(body)['port'] - port = dhcp.DictModel(port_dict) - # pylint: disable=assigning-non-slot - port.network = network - for fixed_ip in port.fixed_ips: - fixed_ip.subnet = self._get_subnet(fixed_ip.subnet_id) - return port diff --git a/neutron/debug/shell.py b/neutron/debug/shell.py deleted file mode 100644 index 25715ac084..0000000000 --- a/neutron/debug/shell.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright 2012, Nachi Ueno, NTT MCL, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sys - -from oslo_config import cfg -from oslo_utils import importutils - -from neutron._i18n import _ -from neutron.agent.common import utils -from neutron.common import config as common_config -from neutron.conf.agent import common as config -from neutron.conf.plugins.ml2.drivers import ovs_conf -from neutron.debug import debug_agent -from neutronclient.common import exceptions as exc -from neutronclient import shell - -COMMAND_V2 = { - 'probe-create': importutils.import_class( - 'neutron.debug.commands.CreateProbe'), - 'probe-delete': importutils.import_class( - 'neutron.debug.commands.DeleteProbe'), - 'probe-list': importutils.import_class( - 'neutron.debug.commands.ListProbe'), - 'probe-clear': importutils.import_class( - 'neutron.debug.commands.ClearProbe'), - 'probe-exec': importutils.import_class( - 'neutron.debug.commands.ExecProbe'), - 'ping-all': importutils.import_class( - 'neutron.debug.commands.PingAll'), - # TODO(nati) ping, netcat , nmap, bench -} -COMMANDS = {'2.0': COMMAND_V2} - - -class NeutronDebugShell(shell.NeutronShell): - def __init__(self, api_version): - super(NeutronDebugShell, self).__init__(api_version) - for k, v in COMMANDS[api_version].items(): - self.command_manager.add_command(k, v) - - def build_option_parser(self, description, version): - parser = super(NeutronDebugShell, self).build_option_parser( - description, version) - default = ( - shell.env('NEUTRON_TEST_CONFIG_FILE') or - shell.env('QUANTUM_TEST_CONFIG_FILE') - ) - parser.add_argument( - '--config-file', - default=default, - help=_('Config file for interface driver ' - '(You may also use l3_agent.ini)')) - return parser - - def initialize_app(self, argv): - super(NeutronDebugShell, self).initialize_app(argv) - if not self.options.config_file: - raise exc.CommandError( - _("You must provide a config file for bridge -" - " either --config-file or env[NEUTRON_TEST_CONFIG_FILE]")) - client = self.client_manager.neutron - config.register_interface_opts() - config.register_interface_driver_opts_helper(cfg.CONF) - ovs_conf.register_ovs_opts(cfg.CONF) - cfg.CONF(['--config-file', self.options.config_file]) - config.setup_logging() - driver = utils.load_interface_driver(cfg.CONF) - self.debug_agent = debug_agent.NeutronDebugAgent(cfg.CONF, - client, - driver) - self.log.warning('This tool is deprecated and will be removed ' - 'in the future to be replaced with a more ' - 'powerful troubleshooting toolkit.') - - -def main(argv=None): - common_config.register_common_config_options() - return NeutronDebugShell(shell.NEUTRON_API_VERSION).run( - argv or sys.argv[1:]) diff --git a/neutron/exceptions/mtu.py b/neutron/exceptions/mtu.py new file mode 100644 index 0000000000..02672d8059 --- /dev/null +++ b/neutron/exceptions/mtu.py @@ -0,0 +1,28 @@ +# Copyright (c) 2023 Canonical Ltd. +# +# 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. + +from neutron_lib import exceptions as e + +from neutron._i18n import _ + + +# TODO(haleyb): Move to n-lib +class NetworkMTUSubnetConflict(e.Conflict): + """A conflict error due to MTU being invalid on said network. + + :param net_id: The UUID of the network + :param mtu: The minimum MTU required by a subnet for the network + """ + message = _("MTU of %(net_id)s is not valid, subnet requires a " + "minimum of %(mtu)s") diff --git a/neutron/extensions/port_hints.py b/neutron/extensions/port_hints.py new file mode 100644 index 0000000000..74e9e6007c --- /dev/null +++ b/neutron/extensions/port_hints.py @@ -0,0 +1,20 @@ +# Copyright 2023 Ericsson Software Technology +# +# 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. + +from neutron_lib.api.definitions import port_hints as phints_def +from neutron_lib.api import extensions as api_extensions + + +class Port_hints(api_extensions.APIExtensionDescriptor): + api_definition = phints_def diff --git a/neutron/locale/de/LC_MESSAGES/neutron.po b/neutron/locale/de/LC_MESSAGES/neutron.po index bf70969899..a1f15f7d20 100644 --- a/neutron/locale/de/LC_MESSAGES/neutron.po +++ b/neutron/locale/de/LC_MESSAGES/neutron.po @@ -12,7 +12,7 @@ msgid "" msgstr "" "Project-Id-Version: neutron VERSION\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2023-01-26 15:02+0000\n" +"POT-Creation-Date: 2023-05-15 17:54+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -152,25 +152,10 @@ msgstr "Fügt Testattribute zu Kernressourcen hinzu." msgid "Agent %(id)s is not a L3 Agent or has been disabled" msgstr "Agent %(id)s ist kein L3-Agent oder wurde inaktiviert" -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 agent " -"until admin changes admin_state_up to True." -msgstr "" -"Agent startet mit admin_state_up=False, wenn enable_new_agents=False. In " -"diesem Fall werden die Ressourcen eines Benutzers nur dann automatisch für " -"den Agenten geplant, wenn der Administrator admin_state_up auf True festlegt." - #, python-format msgid "Agent updated: %(payload)s" msgstr "Agent aktualisiert: %(payload)s" -msgid "Allow auto scheduling networks to DHCP agent." -msgstr "Automatische Netzzuordnung zum DHCP-Agenten zulassen." - -msgid "Allow auto scheduling of routers to L3 agent." -msgstr "Automatische Routerzuordnung zum L3-Agenten zulassen." - msgid "Allow running metadata proxy." msgstr "Aktiven Metadaten-Proxy zulassen." @@ -185,10 +170,6 @@ msgstr "Erstellen von PTR-Datensätzen zulassen" msgid "Allow the usage of the bulk API" msgstr "Nutzung der Massenzuweisungs-API zulassen" -msgid "Allow to perform insecure SSL (https) requests to nova metadata" -msgstr "" -"Durchführung von unsicheren SSL-Anforderungen (HTTPS) an Nova-Metadaten" - msgid "" "Allows for serving metadata requests coming from a dedicated metadata access " "network whose CIDR is 169.254.169.254/16 (or larger prefix), and is " @@ -407,9 +388,6 @@ msgstr "" msgid "Cleanup resources of a specific agent type only." msgstr "Bereinigen Sie nur Ressourcen mit einem bestimmten Agententyp." -msgid "Client certificate for nova metadata api server." -msgstr "Clientzertifikat zu API-Server für Nova-Metadaten." - msgid "" "Comma-separated list of <network_device>:<vfs_to_exclude> tuples, mapping " "network_device to the agent's node-specific list of virtual functions that " @@ -499,27 +477,10 @@ msgstr "" "Durch Kommas getrennte Liste der DNS-Server, die künftig als " "Weiterleitungsserver verwendet werden." -msgid "Command to execute" -msgstr "Auszuführender Befehl" - -msgid "Config file for interface driver (You may also use l3_agent.ini)" -msgstr "" -"Konfigurationsdatei für Schnittstellentreiber (Sie können auch 'l3_agent." -"ini' verwenden)" - #, python-format msgid "Conflicting value ethertype %(ethertype)s for CIDR %(cidr)s" msgstr "Kollidierender Wert bei Ethernet-Typ %(ethertype)s für CIDR %(cidr)s" -msgid "" -"Controls whether the neutron security group API is enabled in the server. It " -"should be false when using no security groups or using the nova security " -"group API." -msgstr "" -"Steuert, ob die Neutron-Sicherheitsgruppen-API im Server aktiviert ist. " -"Sollte 'false' sein, wenn keine Sicherheitsgruppen verwendet werden oder " -"wenn die Nova-Sicherheitsgruppen-API verwendet wird." - #, python-format msgid "Could not bind to %(host)s:%(port)s after trying for %(time)d seconds" msgstr "" @@ -578,13 +539,6 @@ msgstr "" "Standardanzahl an zulässigen RBAC-Einträgen pro Nutzer. Ein negativer Wert " "bedeutet unbegrenzt." -msgid "" -"Default number of resource allowed per tenant. A negative value means " -"unlimited." -msgstr "" -"Standardanzahl an zulässigen Ressourcen pro Nutzer. Ein negativer Wert " -"bedeutet unbegrenzt." - msgid "Default security group" msgstr "Standardsicherheitsgruppe" @@ -658,22 +612,6 @@ msgstr "Treiber für externe DNS-Integration." msgid "Driver for security groups firewall in the L2 agent" msgstr "Treiber für Sicherheitsgruppen-Firewall im L2-Agenten" -msgid "Driver to use for scheduling network to DHCP agent" -msgstr "Zu verwendender Treiber bei Netzzuordnung zum DHCP-Agenten" - -msgid "Driver to use for scheduling router to a default L3 agent" -msgstr "Zu verwendender Treiber bei Routerzuordnung zum Standard-L3-Agenten" - -msgid "" -"Driver used for ipv6 prefix delegation. This needs to be an entry point " -"defined in the neutron.agent.linux.pd_drivers namespace. See setup.cfg for " -"entry points included with the neutron source." -msgstr "" -"Treiber, der für die IPv6-Präfixdelegierung verwendet wird. Dies muss ein " -"Einstiegspunkt sein, der im Namensbereich neutron.agent.linux.pd_drivers " -"definiert ist. In setup.cfg finden Sie die Einstiegspunkte, die in der " -"Neutron-Quelle enthalten sind." - #, python-format msgid "" "Duplicate L3HARouterAgentPortBinding is created for router(s) %(router)s. " @@ -719,13 +657,6 @@ msgid "Enable SSL on the API server" msgstr "SSL auf dem API-Server aktivieren" msgid "" -"Enable VXLAN on the agent. Can be enabled when agent is managed by ml2 " -"plugin using linuxbridge mechanism driver" -msgstr "" -"VXLAN auf dem Agenten aktivieren. Kann aktiviert werden, wenn der Agent vom " -"ml2-Plug-in mithilfe eines Linuxbridge-Mechanismus-Treibers verwaltet wird" - -msgid "" "Enable local ARP responder which provides local responses instead of " "performing ARP broadcast into the overlay. Enabling local ARP responder is " "not fully compatible with the allowed-address-pairs extension." @@ -791,14 +722,6 @@ msgstr "" "Der Erweiterungstreiber %(driver)s, der für das Dienste-Plugin " "%(service_plugin)s erforderlich ist, wurde nicht gefunden." -msgid "" -"Extension to use alongside ml2 plugin's l2population mechanism driver. It " -"enables the plugin to populate VXLAN forwarding table." -msgstr "" -"Erweiterung zur Verwendung mit dem l2population-Mechanismus-Treiber des ml2-" -"Plug-ins. Sie ermöglicht dem Plug-in das Belegen der VXLAN-" -"Weiterleitungstabelle." - #, python-format msgid "Extension with alias %s does not exist" msgstr "Erweiterung mit Alias %s ist nicht vorhanden" @@ -903,18 +826,6 @@ msgstr "" "ICMP-Code (port-range-max) %(value)s ist angegeben, aber ICMP-Typ (port-" "range-min) fehlt." -msgid "ID of network" -msgstr "Netz-ID" - -msgid "ID of network to probe" -msgstr "ID von Netz das überprüft werden soll" - -msgid "ID of probe port to delete" -msgstr "ID von Überprüfungsport der gelöscht werden soll" - -msgid "ID of probe port to execute command" -msgstr "ID von Überprüfungsport zum Ausführen des Befehls" - msgid "ID of the router" msgstr "ID des Routers" @@ -977,19 +888,6 @@ msgid "Illegal IP version number" msgstr "Illegale IP-Versionsnummer" msgid "" -"In some cases the Neutron router is not present to provide the metadata IP " -"but the DHCP server can be used to provide this info. Setting this value " -"will force the DHCP server to append specific host routes to the DHCP " -"request. If this option is set, then the metadata service will be activated " -"for all the networks." -msgstr "" -"In einigen Fällen ist kein Neutron-Router vorhanden, um die Metadaten-IP " -"bereitzustellen. Der DHCP-Server kann jedoch für die Bereitstellung dieser " -"Informationen verwendet werden. Setzen dieses Werts bewirkt, dass der DHCP-" -"Server bestimmte Hostrouten an die DHCP-Anforderung anhängt. Bei Aktivierung " -"dieser Option wird der Metadatendienst für alle Netze aktiviert. " - -msgid "" "Indicates that this L3 agent should also handle routers that do not have an " "external network gateway configured. This option should be True only for a " "single agent in a Neutron deployment, and may be False for all agents if all " @@ -1033,12 +931,6 @@ msgstr "" msgid "Interface to monitor" msgstr "Zu überwachende Schnittstelle" -msgid "" -"Interval between checks of child process liveness (seconds), use 0 to disable" -msgstr "" -"Intervall zwischen Überprüfungen der Aktivität von untergeordneten Prozessen " -"(Sekunden), verwenden Sie zum Deaktivieren '0'" - msgid "Interval between two metering measures" msgstr "Intervall zwischen zwei Messungsmaßnahmen" @@ -1126,14 +1018,6 @@ msgid "Invalid value for port %(port)s" msgstr "Ungültiger Wert für Port %(port)s" msgid "" -"Iptables mangle mark used to mark ingress from external network. This mark " -"will be masked with 0xffff so that only the lower 16 bits will be used." -msgstr "" -"Iptables-Mangling-Markierung zum Markieren des Eingangs vom externen Netz. " -"Diese Markierung wird mit 0xffff maskiert, sodass nur die unteren 16 Bits " -"verwendet werden." - -msgid "" "Iptables mangle mark used to mark metadata valid requests. This mark will be " "masked with 0xffff so that only the lower 16 bits will be used." msgstr "" @@ -1141,14 +1025,6 @@ msgstr "" "Anforderungen. Diese Markierung wird mit 0xffff maskiert, sodass nur die " "unteren 16 Bits verwendet werden." -msgid "" -"Keep in track in the database of current resource quota usage. Plugins which " -"do not leverage the neutron database should set this flag to False." -msgstr "" -"Überwachen der aktuellen Kontingentnutzung in der Datenbank. Bei Plugins, " -"die die Neutron-Datenbank nicht verwenden, sollte dieses Flag auf False " -"festgelegt werden" - msgid "Keepalived didn't respawn" msgstr "Keepalived wurde nicht generiert" @@ -1204,12 +1080,6 @@ msgstr "Position von UNIX-Domänensocket von Metadatenproxy" msgid "Location to store DHCP server config files." msgstr "Position zum Speichern von Konfigurationsdateien des DHCP-Servers." -msgid "Location to store IPv6 PD files." -msgstr "Position zum Speichern von IPv6-PD-Dateien." - -msgid "Location to store IPv6 RA config files" -msgstr "Position zum Speichern von IPv6-RA-Konfigurationsdateien" - msgid "Location to store child pid files" msgstr "Position zum Speichern von untergeordneten PID-Dateien" @@ -1291,10 +1161,6 @@ msgstr "" msgid "MinRtrAdvInterval setting for radvd.conf" msgstr "MinRtrAdvInterval-Einstellung für radvd.conf" -msgid "Minimize polling by monitoring ovsdb for interface changes." -msgstr "" -"Abfrage minimieren durch Überwachung von ovsdb auf Schnittstellenänderungen." - #, python-format msgid "Missing key in mapping: '%s'" msgstr "Fehlender Schlüssel in Zuordnung: '%s'" @@ -1308,22 +1174,6 @@ msgstr "" "Broadcastverkehr an diese Multicastgruppe gesendet werden. Ohne " "Konfiguration ist der Multicast-VXLAN-Modus inaktiviert." -msgid "" -"Multicast group(s) for vxlan interface. A range of group addresses may be " -"specified by using CIDR notation. Specifying a range allows different VNIs " -"to use different group addresses, reducing or eliminating spurious broadcast " -"traffic to the tunnel endpoints. To reserve a unique group for each possible " -"(24-bit) VNI, use a /8 such as 239.0.0.0/8. This setting must be the same on " -"all the agents." -msgstr "" -"Multicastgruppe(n) für VXLAN-Schnittstelle. Ein Gruppenadressbereich, der " -"mit der CIDR-Notation angegeben werden kann. Durch die Angabe eines Bereichs " -"können unterschiedliche VNIs verschiedene Gruppenadressen verwenden und so " -"fehlerhaften Broadcastverkehr an Tunnelendpunkt senkden oder entfernen. Wenn " -"Sie eine eindeutige Gruppe für jede mögliche VNI (24 Bit) reservieren " -"möchten, verwenden Sie die Einstellung /8, wie z. B. 239.0.0.0/8. Diese " -"Einstellung muss für alle Agenten gleich sein." - #, python-format msgid "Multiple default providers for service %s" msgstr "Mehrere Standardanbieter für Dienst %s" @@ -1349,19 +1199,6 @@ msgstr "" msgid "Name of Open vSwitch bridge to use" msgstr "Name der zu verwendenden Open vSwitch-Brücke" -msgid "" -"Name of nova region to use. Useful if keystone manages more than one region." -msgstr "" -"Name der zu verwendenden Nova-Region. Nützlich, wenn Keystone mehrere " -"Regionen verwaltet. " - -msgid "" -"Name of placement region to use. Useful if keystone manages more than one " -"region." -msgstr "" -"Name der zu verwendenden Placement-Region. Nützlich, wenn Keystone mehrere " -"Regionen verwaltet. " - msgid "Namespace of the router" msgstr "Namensbereich des Routers" @@ -1444,21 +1281,6 @@ msgstr "" "Es ist nicht zulässig, einen Router aus einem Agenten im Modus 'dvr' manuell " "zu entfernen." -msgid "" -"Number of DHCP agents scheduled to host a tenant network. If this number is " -"greater than 1, the scheduler automatically assigns multiple DHCP agents for " -"a given tenant network, providing high availability for DHCP service." -msgstr "" -"Anzahl der DHCP-Agenten, die zum Hosten eines Mandatennetzwerkes geplant " -"werden. Wenn diese Zahl größer als 1 ist, weist der Scheduler automatisch " -"mehrere DHCP-Agenten für ein angegebenes Nutzernetz zu, wodurch " -"Hochverfügbarkeit für den DHCP-Service erreicht wird." - -msgid "Number of RPC worker processes dedicated to state reports queue." -msgstr "" -"Anzahl der RPC-Worker-Prozesse, die der Statusberichtswarteschlange " -"zugewiesen ist." - msgid "Number of backlog requests to configure the metadata server socket with" msgstr "" "Anzahl der Rückstandanforderungen, mit denen der Metadatenserver-Socket " @@ -1470,26 +1292,6 @@ msgstr "" "soll" msgid "" -"Number of bits in an ipv4 PTR zone that will be considered network prefix. " -"It has to align to byte boundary. Minimum value is 8. Maximum value is 24. " -"As a consequence, range of values is 8, 16 and 24" -msgstr "" -"Anzahl von Bits in einer ipv4-PTR-Zone, die als Netzpräfix betrachtet wird. " -"Es muss an der Bytegrenze ausgerichtet werden. Der Mindestwert ist 8. Der " -"maximal zulässige Wert ist 24. Daraus ergibt sich ein Wertebereich von 8, 16 " -"und 24. " - -msgid "" -"Number of bits in an ipv6 PTR zone that will be considered network prefix. " -"It has to align to nyble boundary. Minimum value is 4. Maximum value is 124. " -"As a consequence, range of values is 4, 8, 12, 16,..., 124" -msgstr "" -"Anzahl von Bits in einer ipv6-PTR-Zone, die als Netzpräfix betrachtet wird. " -"Es muss an der nyble-Grenze ausgerichtet werden. Der Mindestwert ist 4. Der " -"maximal zulässige Wert ist 124. Daraus ergibt sich ein Wertebereich von 4, " -"8, 12, 16,..., 124." - -msgid "" "Number of floating IPs allowed per tenant. A negative value means unlimited." msgstr "" "Anzahl an zulässigen dynamischen IPs pro Nutzer. Ein negativer Wert bedeutet " @@ -1511,13 +1313,6 @@ msgstr "" "Anzahl an zulässigen Routern pro Nutzer. Ein negativer Wert bedeutet " "unbegrenzt." -msgid "" -"Number of seconds between sending events to nova if there are any events to " -"send." -msgstr "" -"Anzahl der Sekunden zwischen dem Senden von Ereignissen an Nova, wenn " -"Ereignisse zum Senden vorhanden sind. " - msgid "Number of seconds to keep retrying to listen" msgstr "" "Anzahl der Sekunden, in denen wiederholt versucht wird, empfangsbereit zu " @@ -1530,13 +1325,6 @@ msgstr "" "Anzahl an zulässigen Sicherheitsgruppen pro Nutzer. Ein negativer Wert " "bedeutet unbegrenzt." -msgid "" -"Number of security rules allowed per tenant. A negative value means " -"unlimited." -msgstr "" -"Anzahl an zulässigen Sicherheitsregeln pro Nutzer. Ein negativer Wert " -"bedeutet unbegrenzt." - msgid "Number of subnets allowed per tenant, A negative value means unlimited." msgstr "" "Anzahl an zulässigen Teilnetzen pro Nutzer. Ein negativer Wert bedeutet " @@ -1593,9 +1381,6 @@ msgstr "" msgid "Override the default dnsmasq settings with this file." msgstr "Standard-'dnsmasq'-Einstellungen mit dieser Datei außer Kraft setzen." -msgid "Owner type of the device: network/compute" -msgstr "Eigentümertyp des Geräts: Netz/Rechenknoten" - msgid "POST requests are not supported on this resource." msgstr "POST-Anforderungen werden auf dieser Ressource nicht unterstützt." @@ -1627,9 +1412,6 @@ msgstr "Peer-Patch-Port in Tunnelbrücke für Integrationsbrücke." msgid "Phase upgrade options do not accept revision specification" msgstr "Phasenupgradeoptionen akzeptieren keine Revisionsspezifikation" -msgid "Ping timeout" -msgstr "Ping-Zeitlimitüberschreitung" - #, python-format msgid "Port %(id)s does not have fixed ip %(address)s" msgstr "Port %(id)s verfügt nicht über statische IP-Adresse %(address)s" @@ -1656,23 +1438,12 @@ msgstr "Präfixdelegierung kann nur bei IPv6-Teilnetzen verwendet werden." msgid "Private key of client certificate." msgstr "Privater Schlüssel für Clientzertifikat." -#, python-format -msgid "Probe %s deleted" -msgstr "Stichprobe %s gelöscht" - -#, python-format -msgid "Probe created : %s " -msgstr "Stichprobe erstellt: %s " - msgid "Process is already started" msgstr "Prozess wurde bereits gestartet" msgid "Process is not running." msgstr "Prozess läuft nicht." -msgid "Protocol to access nova metadata, http or https" -msgstr "Protokoll für den Zugriff auf Nova-Metadaten, HTTP oder HTTPS" - #, python-format msgid "Provider name %(name)s is limited by %(len)s characters" msgstr "Der Providername %(name)s ist auf %(len)s Zeichen begrenzt." @@ -1724,29 +1495,6 @@ msgid "" msgstr "" "Das Repository enthält keine HEAD-Dateien für Contract- und Expand-Branches. " -msgid "" -"Representing the resource type whose load is being reported by the agent. " -"This can be \"networks\", \"subnets\" or \"ports\". When specified (Default " -"is networks), the server will extract particular load sent as part of its " -"agent configuration object from the agent report state, which is the number " -"of resources being consumed, at every report_interval.dhcp_load_type can be " -"used in combination with network_scheduler_driver = neutron.scheduler." -"dhcp_agent_scheduler.WeightScheduler When the network_scheduler_driver is " -"WeightScheduler, dhcp_load_type can be configured to represent the choice " -"for the resource being balanced. Example: dhcp_load_type=networks" -msgstr "" -"Darstellung des Ressourcentyps, zu dessen Arbeitslast vom Agenten Bericht " -"erstattet wird. Dies kann \"networks\", \"subnets\" oder \"ports\" sein. Bei " -"Angabe (Standardwert ist 'networks') extrahiert der Server bei jedem " -"report_interval eine bestimmte Arbeitslast, die als Teil des " -"Agentenkonfigurationsobjekts vom Agentenberichtsstatus, der der Anzahl der " -"konsumierten Ressourcen entspricht, gesendet wird. dhcp_load_type kann in " -"Verbindung mit network_scheduler_driver = neutron.scheduler." -"dhcp_agent_scheduler.WeightScheduler verwendet werden. Wenn der " -"network_scheduler_driver WeightScheduler ist, kann dhcp_load_type so " -"konfiguriert werden, dass die Auswahl für die Ressource mit Lastausgleich " -"dargestellt wird. Beispiel: dhcp_load_type=networks" - msgid "Request Failed: internal server error while processing your request." msgstr "" "Anforderung fehlgeschlagen: interner Serverfehler bei Verarbeitung Ihrer " @@ -1830,14 +1578,6 @@ msgstr "" msgid "Seconds between running periodic tasks." msgstr "Sekunden zwischen Ausführungen regelmäßig wiederkehrender Tasks." -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 "" -"Sekunden bis zur Annahme, dass der Agent inaktiv ist; sollte mindestens " -"doppelt so hoch sein wie report_interval, damit sichergestellt ist, dass der " -"Agent wirklich inaktiv ist." - #, python-format msgid "Security Group %(id)s %(reason)s." msgstr "Sicherheitsgruppe %(id)s %(reason)s." @@ -1877,16 +1617,6 @@ msgstr "" "Protokollwerte %(values)s und ganzzahlige Darstellungen [0 bis 255] werden " "unterstützt." -msgid "" -"Send notification to nova when port data (fixed_ips/floatingip) changes so " -"nova can update its cache." -msgstr "" -"Benachrichtigung an Nova senden, wenn sich die Portdaten (fixed_ips/" -"floatingip) ändern, damit Nova den Zwischenspeicher aktualisieren kann. " - -msgid "Send notification to nova when port status changes" -msgstr "Benachrichtigung an Nova senden, wenn sich der Portstatus ändert" - #, python-format msgid "" "Service provider '%(provider)s' could not be found for service type " @@ -1902,21 +1632,6 @@ msgstr "Service zum Behandeln der DHCPv6-Präfixdelegierung." msgid "Service type %(service_type)s does not have a default service provider" msgstr "Dienstetyp %(service_type)s weist keinen Standard-Diensteanbieter auf" -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 "" -"Neues Zeitlimit in Sekunden für neue RPC-Aufrufe festlegen, nachdem Agent " -"SIGTERM empfängt. Wenn der Wert auf 0 gesetzt ist, wird das RPC-Zeitlimit " -"nicht geändert" - -msgid "" -"Set or un-set the don't fragment (DF) bit on outgoing IP packet carrying GRE/" -"VXLAN tunnel." -msgstr "" -"DF-Bit (Don't Fragment) auf GRE/VXLAN-Tunnel für abgehende IP-Pakete " -"festlegen oder die Festlegung aufheben." - msgid "Shared address scope can't be unshared" msgstr "" "Freigabe des gemeinsam genutzten Adressbereichs kann nicht aufgehoben werden" @@ -1935,11 +1650,6 @@ msgstr "" msgid "Subnet pool has existing allocations" msgstr "Der Teilnetzpool verfügt über vorhandene Zuordnungen" -msgid "Subnet used for the l3 HA admin network." -msgstr "" -"Teilnetz, das für das L3-Verwaltungsnetz für hohe Verfügbarkeit verwendet " -"wird." - msgid "" "System-wide flag to determine the type of router that tenants can create. " "Only admin can override." @@ -1953,9 +1663,6 @@ msgstr "Von Neutron-Metadaten-Namensbereichsproxy verwendeter TCP-Port." msgid "TCP Port used by Nova metadata server." msgstr "Von Nova-Metadatenserver verwendeter TCP-Port." -msgid "TTL for vxlan interface protocol packets." -msgstr "TTL für VXLAN-Schnittstellenprotokollpakete." - #, python-format msgid "Tag %(tag)s could not be found." msgstr "Schlagwort %(tag)s konnte nicht gefunden werden." @@ -1974,22 +1681,6 @@ msgstr "" "Mandantenname zum Herstellen einer Verbindung zu Designate im " "Administratorkontext." -msgid "" -"The DHCP server can assist with providing metadata support on isolated " -"networks. Setting this value to True will cause the DHCP server to append " -"specific host routes to the DHCP request. The metadata service will only be " -"activated when the subnet does not contain any router port. The guest " -"instance must be configured to request host routes via DHCP (Option 121). " -"This option doesn't have any effect when force_metadata is set to True." -msgstr "" -"Der DHCP-Server kann zur Bereitstellung von Metadatenunterstützung für " -"isolierte Netze beitragen. Wenn Sie diesen Wert auf 'True' setzen, hängt der " -"DHCP-Server bestimmte Hostrouten an die DHCP-Anforderung an. Der " -"Metadatendienst wird nur aktiviet, wenn das Subnetz keinen Router-Port " -"enthält. Die Gastinstanz muss so konfiguriert sein, dass Hostrouten über " -"DHCP (Option 121) angefordert werden. Diese Option ist wirkungslos, wenn " -"'force_metadata' auf 'True' gesetzt wird." - msgid "The UDP port to use for VXLAN tunnels." msgstr "UDP-Port für VXLAN-Tunnel." @@ -2011,32 +1702,12 @@ msgstr "" "Oktetts bleiben unverändert. Wenn das vierte Oktett nicht 00 ist, wird es " "ebenfalls verwendet. Die anderen werden zufällig generiert. " -msgid "" -"The base mac address used for unique DVR instances by Neutron. The first 3 " -"octets will remain unchanged. If the 4th octet is not 00, it will also be " -"used. The others will be randomly generated. The 'dvr_base_mac' *must* be " -"different from 'base_mac' to avoid mixing them up with MAC's allocated for " -"tenant ports. A 4 octet example would be dvr_base_mac = fa:16:3f:4f:00:00. " -"The default is 3 octet" -msgstr "" -"Die MAC-Basisadresse, die durch Neutron für eindeutige DVR-Instanzen " -"verwendet wird. Die ersten 3 Oktetts bleiben unverändert. Wenn das 4. Oktett " -"nicht 00 ist, wird es ebenfalls verwendet. Die anderen werden zufällig " -"generiert. Die 'dvr_base_mac' *muss* sich von 'base_mac' unterscheiden, um " -"eine Vermischung mit zugeordneten MACs für Nutzerports zu vermeiden. " -"Beispiel mit 4 Oktetts: dvr_base_mac = fa:16:3f:4f:00:00. Standardmäßig " -"werden 3 Oktetts verwendet" - msgid "The core plugin Neutron will use" msgstr "Core-Plugin, das Neutron verwenden wird" msgid "The driver used to manage the DHCP server." msgstr "Der für die Verwaltung des DHCP-Servers verwendete Treiber." -msgid "The driver used to manage the virtual interface." -msgstr "" -"Der für die Verwaltung der virtuellen Schnittstelle verwendete Treiber." - msgid "" "The email address to be used when creating PTR zones. If not specified, the " "email address will be admin@<dns_domain>" @@ -2048,58 +1719,15 @@ msgid "The host IP to bind to." msgstr "Die Host-IP, an die gebunden werden soll." msgid "" -"The maximum number of items returned in a single response, value was " -"'infinite' or negative integer means no limit" -msgstr "" -"Maximale Anzahl an in einer einzelnen Antwort zurückgegebenen Elementen. Der " -"Wert 'infinite' oder eine negative Ganzzahl bedeuten, dass es keine " -"Begrenzung gibt." - -msgid "" -"The network type to use when creating the HA network for an HA router. By " -"default or if empty, the first 'tenant_network_types' is used. This is " -"helpful when the VRRP traffic should use a specific network which is not the " -"default one." -msgstr "" -"Der Netztyp, der beim Erstellen des HA-Netzes für einen HA-Router verwendet " -"werden soll. Standardmäßig oder bei fehlender Angabe wird das erste " -"'tenant_network_types' verwendet. Dies ist hilfreich, wenn der VRRP-" -"Datenverkehr ein bestimmtes Netz verwenden soll, das nicht das Standardnetz " -"ist." - -msgid "" "The number of seconds the agent will wait between polling for local device " "changes." msgstr "" "Die Anzahl an Sekunden, die der Agent zwischen Abfragen lokaler " "Geräteänderungen wartet." -msgid "" -"The number of seconds to wait before respawning the ovsdb monitor after " -"losing communication with it." -msgstr "" -"Die Anzahl an Sekunden, die gewartet werden soll, bevor die ovsdb-" -"Überwachung nach einer Kommunikationsunterbrechung erneut generiert wird." - msgid "The number of sort_keys and sort_dirs must be same" msgstr "Die Anzahl an 'sort_keys' und 'sort_dirs' muss gleich sein" -msgid "" -"The path for API extensions. Note that this can be a colon-separated list of " -"paths. For example: api_extensions_path = extensions:/path/to/more/exts:/" -"even/more/exts. The __path__ of neutron.extensions is appended to this, so " -"if your extensions are in there you don't need to specify them here." -msgstr "" -"Der Pfad für API-Erweiterungen. Beachten Sie, dass dies eine durch Punkte " -"getrennte Liste von Pfaden sein kann. Beispiel: api_extensions_path = " -"extensions:/path/to/more/exts:/even/more/exts. An diesen Pfad wird '__path__ " -"of neutron.extensions' angehängt, sodass Sie Ihre Erweiterungen hier nicht " -"mehr angeben müssen, wenn Sie dort bereits angegeben wurden." - -msgid "The physical network name with which the HA network can be created." -msgstr "" -"Der Name des physischen Netzes, mit dem das HA-Netz erstellt werden kann." - #, python-format msgid "The port '%s' was deleted" msgstr "Port '%s' wurde gelöscht" @@ -2151,13 +1779,6 @@ msgstr "" "Diesem Netz sind Router zugeordnet, die für den Zugriff von dieser " "Richtlinie abhängig sind." -msgid "" -"Timeout in seconds for ovsdb commands. If the timeout expires, ovsdb " -"commands will fail with ALARMCLOCK error." -msgstr "" -"Zeitlimit in Sekunden für ovsdb-Befehle. Wenn das Zeitlimit abgelaufen ist, " -"schlagen ovsdb-Befehle mit einem Fehler vom Typ ALARMCLOCK fehl." - msgid "Timeout in seconds to wait for a single OpenFlow request." msgstr "" "Zeitlimit in Sekunden für die Wartezeit auf eine einzelne OpenFlow-" @@ -2175,21 +1796,6 @@ msgstr "Tunnel-IP-Wert für ML2-Plug-in erforderlich" msgid "Tunnel bridge to use." msgstr "Zu verwendende Tunnelbrücke." -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 "" -"Typ des zu verwendenden Nova-Endpunkts. Dieser Endpunkt wird im Keystone-" -"Katalog gesucht und muss vom Typ 'public', 'internal' oder 'admin' sein." - -msgid "" -"Type of the placement endpoint to use. This endpoint will be looked up in " -"the keystone catalog and should be one of public, internal or admin." -msgstr "" -"Typ des zu verwendenden Placement-Endpunkts. Dieser Endpunkt wird im " -"Keystone-Katalog gesucht und muss vom Typ 'public', 'internal' oder 'admin' " -"sein." - msgid "URL for connecting to designate" msgstr "URL zum Herstellen einer Verbindung zu Designate. " @@ -2310,15 +1916,6 @@ msgstr "" "Verwenden Sie entweder --delta oder relative Revision, nicht beides gemeinsam" msgid "" -"Use ipset to speed-up the iptables based security groups. Enabling ipset " -"support requires that ipset is installed on L2 agent node." -msgstr "" -"Verwenden Sie ipset, um die Geschwindigkeit der auf iptables basierenden " -"Sicherheitsgruppen zu verbessern. Für die Aktivierung der ipset-" -"Unterstützung ist es erforderlich, dass ipset auf einem L2-Agentenknoten " -"installiert ist." - -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." @@ -2369,62 +1966,15 @@ msgstr "" "einen Port mit QoS. Weitere Informationen finden Sie im tc-tbf-Handbuch." msgid "" -"When proxying metadata requests, Neutron signs the Instance-ID header with a " -"shared secret to prevent spoofing. You may select any string for a secret, " -"but it must match here and in the configuration used by the Nova Metadata " -"Server. NOTE: Nova uses the same config key, but in [neutron] section." -msgstr "" -"Beim Proxy-Vorgang von Metadatenanforderungen unterzeichnet Neutron den " -"Instanz-ID-Header mit einem geheimen Schlüssel für gemeinsame Nutzung, um " -"Spoofing zu verhindern. Sie können für einen geheimen Schlüssel eine " -"beliebige Zeichenfolge auswählen. Sie muss jedoch hier und in der vom Nova-" -"Metadatenserver verwendeten Konfiguration identisch sein. Hinweis: Nova " -"verwendet denselben Konfigurationsschlüssel, allerdings im Abschnitt " -"[neutron]." - -msgid "" "Where to store Neutron state files. This directory must be writable by the " "agent." msgstr "" "Position zum Speichern von Neutron-Statusdateien. Dieses Verzeichnis muss " "für den Agenten beschreibbar sein." -msgid "" -"With IPv6, the network used for the external gateway does not need to have " -"an associated subnet, since the automatically assigned link-local address " -"(LLA) can be used. However, an IPv6 gateway address is needed for use as the " -"next-hop for the default route. If no IPv6 gateway address is configured " -"here, (and only then) the neutron router will be configured to get its " -"default route from router advertisements (RAs) from the upstream router; in " -"which case the upstream router must also be configured to send these RAs. " -"The ipv6_gateway, when configured, should be the LLA of the interface on the " -"upstream router. If a next-hop using a global unique address (GUA) is " -"desired, it needs to be done via a subnet allocated to the network and not " -"through this parameter. " -msgstr "" -"Mit IPv6 benötigt das Netz, das für das externe Gateway verwendet wird, kein " -"zugehöriges Teilnetz, da die automatisch zugewiesene LLA (Link-Local " -"Address) verwendet werden kann. Eine IPv6-Gateway-Adresse ist jedoch für die " -"Verwendung als Next-Hop für die Standardroute erforderlich. Ist hier keine " -"IPv6-Gateway-Adresse konfiguriert (und nur dann), wird der Neutron-Router so " -"konfiguriert, dass er die Standardroute von RAs (Router Advertisements) vom " -"vorgeschalteten Router erhält; in diesem Fall muss der vorgeschaltete Router " -"ebenfalls zum Senden dieser RAs konfiguriert sein. Wenn das ipv6_gateway " -"konfiguriert ist, sollte es die LLA der Schnittstelle auf dem " -"vorgeschalteten Router sein. Wenn ein Next-Hop benötigt wird, der eine GUA " -"(Global Unique Address) verwendet, muss dies über ein Teilnetz geschehen, " -"das dem Netz zugeordnet ist, nicht über diesen Parameter. " - msgid "You must implement __call__" msgstr "Sie müssen '__call__' implementieren" -msgid "" -"You must provide a config file for bridge - either --config-file or " -"env[NEUTRON_TEST_CONFIG_FILE]" -msgstr "" -"Sie müssen eine Konfigurationsdatei für die Brücke angeben: entweder '--" -"config-file' oder env[NEUTRON_TEST_CONFIG_FILE]" - msgid "You must provide a revision or relative delta" msgstr "Sie müssen eine Überarbeitung oder ein relatives Delta bereitstellen" diff --git a/neutron/locale/es/LC_MESSAGES/neutron.po b/neutron/locale/es/LC_MESSAGES/neutron.po index 2b935d126c..7dbd9f9f81 100644 --- a/neutron/locale/es/LC_MESSAGES/neutron.po +++ b/neutron/locale/es/LC_MESSAGES/neutron.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: neutron VERSION\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2023-01-26 15:02+0000\n" +"POT-Creation-Date: 2023-05-15 17:54+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -135,25 +135,10 @@ msgstr "Añade atributos de prueba a recursos de núcleo." msgid "Agent %(id)s is not a L3 Agent or has been disabled" msgstr "El agente %(id)s no es un agente L3 válido o se ha inhabilitado" -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 agent " -"until admin changes admin_state_up to True." -msgstr "" -"El agente se inicia con admin_state_up=False cuando enable_new_agents=False. " -"En ese caso, los recursos del usuario no se planificarán automáticamente en " -"el agente hasque que admin cambie admin_state_up a True." - #, python-format msgid "Agent updated: %(payload)s" msgstr "El agente se ha actualizado: %(payload)s" -msgid "Allow auto scheduling networks to DHCP agent." -msgstr "Permita la planificación automática de redes para el agente DHCP." - -msgid "Allow auto scheduling of routers to L3 agent." -msgstr "Permitir auto programación de enrutadores al agente L3." - msgid "Allow running metadata proxy." msgstr "Permitir ejecutar el proxy de metadatos." @@ -167,10 +152,6 @@ msgstr "Permitir la creación de registros PTR" msgid "Allow the usage of the bulk API" msgstr "Permitir el uso de la API masiva" -msgid "Allow to perform insecure SSL (https) requests to nova metadata" -msgstr "" -"Permitir ejecutar solicitudes SSL (https) no seguras en los metadatos de Nova" - msgid "" "Allows for serving metadata requests coming from a dedicated metadata access " "network whose CIDR is 169.254.169.254/16 (or larger prefix), and is " @@ -382,9 +363,6 @@ msgstr "" msgid "Cleanup resources of a specific agent type only." msgstr "Limpiar solo los recursos de un tipo de agente específico." -msgid "Client certificate for nova metadata api server." -msgstr "Certificado de cliente para el servidor de la API de metadatos de Nova" - msgid "" "Comma-separated list of <network_device>:<vfs_to_exclude> tuples, mapping " "network_device to the agent's node-specific list of virtual functions that " @@ -449,27 +427,10 @@ msgstr "" "Lista separada por comas de los servidores DNS que se utilizarán como " "reenviadores." -msgid "Command to execute" -msgstr "Mandato a ejecutar" - -msgid "Config file for interface driver (You may also use l3_agent.ini)" -msgstr "" -"Archivo de configuración para controlador de interfaz (También puede " -"utilizar l3_agent.ini)" - #, python-format msgid "Conflicting value ethertype %(ethertype)s for CIDR %(cidr)s" msgstr "Valor ethertype %(ethertype)s en conflicto para CIDR %(cidr)s" -msgid "" -"Controls whether the neutron security group API is enabled in the server. It " -"should be false when using no security groups or using the nova security " -"group API." -msgstr "" -"Controla si la API de grupo de seguridad neutron está habilitada en el " -"servidor. Debe ser false cuando no hay grupos de seguridad o se utiliza la " -"API de grupo de seguridad nova." - #, python-format msgid "Could not bind to %(host)s:%(port)s after trying for %(time)d seconds" msgstr "" @@ -526,13 +487,6 @@ msgstr "" "Número predeterminado de entradas RBAC permitidas por arrendatario. Un valor " "negativo significa ilimitados." -msgid "" -"Default number of resource allowed per tenant. A negative value means " -"unlimited." -msgstr "" -"Número predeterminado de recursos permitidos por arrendatario. Un valor " -"negativo significa ilimitados." - msgid "Default security group" msgstr "Grupo de seguridad predeterminado" @@ -606,25 +560,6 @@ msgstr "Controlador para la integración externa de DNS." msgid "Driver for security groups firewall in the L2 agent" msgstr "Controlador para el cortafuegos de grupos de seguridad en el agente L2" -msgid "Driver to use for scheduling network to DHCP agent" -msgstr "" -"Controlador que utilizar para la planificación de la red para el agente DHCP" - -msgid "Driver to use for scheduling router to a default L3 agent" -msgstr "" -"Controlador que utilizar para la planificación del direccionador para un " -"agente L3 predeterminado" - -msgid "" -"Driver used for ipv6 prefix delegation. This needs to be an entry point " -"defined in the neutron.agent.linux.pd_drivers namespace. See setup.cfg for " -"entry points included with the neutron source." -msgstr "" -"Controlador utilizado para la delegación de prefijos ipv6. Debe ser un punto " -"de entrada definido en el espacio de nombres neutron.agent.linux.pd_drivers. " -"Consulte setup.cfg para ver los puntos de entrada incluidos con el origen de " -"neutron." - #, python-format msgid "" "Duplicate L3HARouterAgentPortBinding is created for router(s) %(router)s. " @@ -668,13 +603,6 @@ msgid "Enable SSL on the API server" msgstr "Habilitar SSL en el servidor API" msgid "" -"Enable VXLAN on the agent. Can be enabled when agent is managed by ml2 " -"plugin using linuxbridge mechanism driver" -msgstr "" -"Habilitar VXLAN en el agente. Se puede habilitar cuando el agente es " -"gestionado por ml2 plugin usando controlador de mecanismo linuxbridge" - -msgid "" "Enable services on an agent with admin_state_up False. If this option is " "False, when admin_state_up of an agent is turned False, services on it will " "be disabled. Agents with admin_state_up False are not selected for automatic " @@ -730,14 +658,6 @@ msgstr "" "No se ha encontrado el controlador de extensión %(driver)s necesario para el " "plugin de servicio %(service_plugin)s." -msgid "" -"Extension to use alongside ml2 plugin's l2population mechanism driver. It " -"enables the plugin to populate VXLAN forwarding table." -msgstr "" -"Extensión para usar unto con el controlador de mecanismo l2population del " -"plug-in ml2. Este habilita el plugin para completar la tabla de reenvío " -"VXLAN." - #, python-format msgid "Extension with alias %s does not exist" msgstr "La ampliación con el alias %s no existe" @@ -841,18 +761,6 @@ msgstr "" "Se proporciona el código ICMP (port-range-max) %(value)s, pero falta el tipo " "ICMP (port-range-min)." -msgid "ID of network" -msgstr "ID de red" - -msgid "ID of network to probe" -msgstr "ID de red a analizar" - -msgid "ID of probe port to delete" -msgstr "ID de puerto de analizador a suprimir" - -msgid "ID of probe port to execute command" -msgstr "ID de puerto de analizador para ejecutar mandato" - msgid "ID of the router" msgstr "ID del direccionador" @@ -917,20 +825,6 @@ msgid "Illegal IP version number" msgstr "Número de versión IP no permitido" msgid "" -"In some cases the Neutron router is not present to provide the metadata IP " -"but the DHCP server can be used to provide this info. Setting this value " -"will force the DHCP server to append specific host routes to the DHCP " -"request. If this option is set, then the metadata service will be activated " -"for all the networks." -msgstr "" -"En algunos casos, el direccionador Neutron no está presente para " -"proporcionar el IP de los metadatos, pero se puede utilizar el servidor " -"DHCP para proporcionar esta información. Si se define este valor, se forzará " -"al servidor DHCP a añadir rutas de host específicas a la solicitud DHCP. Si " -"no se define esta opción, el servicio de metadatos estará activado para " -"todas las redes." - -msgid "" "Indicates that this L3 agent should also handle routers that do not have an " "external network gateway configured. This option should be True only for a " "single agent in a Neutron deployment, and may be False for all agents if all " @@ -972,12 +866,6 @@ msgstr "" msgid "Interface to monitor" msgstr "Interfaz a supervisar" -msgid "" -"Interval between checks of child process liveness (seconds), use 0 to disable" -msgstr "" -"Intervalo entre comprobaciones de vida de procesos secundarios (segundos), " -"utilice 0 para inhabilitarlo" - msgid "Interval between two metering measures" msgstr "Intervalo entre dos medidas de medición" @@ -1054,14 +942,6 @@ msgid "Invalid value for port %(port)s" msgstr "Valor no válido para el puerto %(port)s" msgid "" -"Iptables mangle mark used to mark ingress from external network. This mark " -"will be masked with 0xffff so that only the lower 16 bits will be used." -msgstr "" -"Marca de corte de iptables utilizada para marcar la entrada desde la red " -"externa. Esta marca se enmascara con 0xffff de modo que sólo se utilizarán " -"los 16 bits inferiores." - -msgid "" "Iptables mangle mark used to mark metadata valid requests. This mark will be " "masked with 0xffff so that only the lower 16 bits will be used." msgstr "" @@ -1119,12 +999,6 @@ msgid "Location to store DHCP server config files." msgstr "" "Ubicación donde almacenar los archivos de configuración de servidor DHCP." -msgid "Location to store IPv6 PD files." -msgstr "Ubicación donde se almacenan los archivos PD de IPv6." - -msgid "Location to store IPv6 RA config files" -msgstr "Ubicación para almacenar archivos de configuración de IPv6 RA" - msgid "Location to store child pid files" msgstr "Ubicación para almacenar archivos pid hijos" @@ -1201,9 +1075,6 @@ msgstr "Controlador de medición" msgid "MinRtrAdvInterval setting for radvd.conf" msgstr "Parámetro MinRtrAdvInterval para radvd.conf" -msgid "Minimize polling by monitoring ovsdb for interface changes." -msgstr "Minimizar sondeo supervisando ovsdb para cambios de interfaz." - #, python-format msgid "Missing key in mapping: '%s'" msgstr "Falta clave en correlación: '%s'" @@ -1217,22 +1088,6 @@ msgstr "" "todo el tráfico de difusión a este grupo de multidifusión. Si se deja sin " "configurar, se deshabilitará el modo de multidifusión VXLAN." -msgid "" -"Multicast group(s) for vxlan interface. A range of group addresses may be " -"specified by using CIDR notation. Specifying a range allows different VNIs " -"to use different group addresses, reducing or eliminating spurious broadcast " -"traffic to the tunnel endpoints. To reserve a unique group for each possible " -"(24-bit) VNI, use a /8 such as 239.0.0.0/8. This setting must be the same on " -"all the agents." -msgstr "" -"Grupo de multidifusión para la interfaz VXLAN. Se puede especificar un rango " -"de direcciones de grupo utilizando la notación CIDR. Especificar un rango " -"permite que diferentes VNI utilicen diferentes direcciones de grupos, " -"reduciendo o eliminando tráfico de difusión espurio a los puntos finales del " -"tunel. Para reservar un grupo exclusivo para cada posible VNI (24-bit) , " -"utilice un /8, como por ejemplo 239.0.0.0/8. Este ajuste debe ser el mismo " -"en todos los agentes." - #, python-format msgid "Multiple default providers for service %s" msgstr "Múltiples proveedores predeterminados para servicio %s" @@ -1257,12 +1112,6 @@ msgstr "" msgid "Name of Open vSwitch bridge to use" msgstr "Nombre de puente de Open vSwitch a utilizar" -msgid "" -"Name of nova region to use. Useful if keystone manages more than one region." -msgstr "" -"Nombre de región de nova a utilizar. Es útil si keystone gestiona más de una " -"región." - msgid "Namespace of the router" msgstr "Espacio de nombres del direccionador" @@ -1343,16 +1192,6 @@ msgstr "" "No está permitido eliminar manualmente un direccionador de un agente en modo " "'dvr'." -msgid "" -"Number of DHCP agents scheduled to host a tenant network. If this number is " -"greater than 1, the scheduler automatically assigns multiple DHCP agents for " -"a given tenant network, providing high availability for DHCP service." -msgstr "" -"Número de agentes DHCP programados para alojar una red de arrendatarios. Si " -"este número es mayor que 1, el planificador asigna automáticamente varios " -"agentes DHCP de una red de arrendatarios dada y proporciona alta " -"disponibilidad para el servicio DHCP." - msgid "Number of backlog requests to configure the metadata server socket with" msgstr "" "Número de solicitudes de retraso para configurar el socket de servidor de " @@ -1363,25 +1202,6 @@ msgstr "" "Número de solicitudes de registro de reserva para configurar el socket con" msgid "" -"Number of bits in an ipv4 PTR zone that will be considered network prefix. " -"It has to align to byte boundary. Minimum value is 8. Maximum value is 24. " -"As a consequence, range of values is 8, 16 and 24" -msgstr "" -"Número de bits en una zona PTR ipv4 que se considerarán prefijo de red. " -"Tiene que estar alineado con el límite de bytes. El valor mínimo es 8. El " -"valor máximo es 24. En consecuencia, el rango de valores es 8, 16 y 24." - -msgid "" -"Number of bits in an ipv6 PTR zone that will be considered network prefix. " -"It has to align to nyble boundary. Minimum value is 4. Maximum value is 124. " -"As a consequence, range of values is 4, 8, 12, 16,..., 124" -msgstr "" -"Número de bits en una zona PTR ipv6 que se considerarán prefijo de red. " -"Tiene que estar alineado con el límite de nyble. El valor mínimo es 4. El " -"valor máximo es 124. En consecuencia, el rango de valores es 4, 8, 12, " -"16,..., 124." - -msgid "" "Number of floating IPs allowed per tenant. A negative value means unlimited." msgstr "" "Número de IP flotantes permitidas por arrendatario. Un valor negativo " @@ -1403,13 +1223,6 @@ msgstr "" "Número de direccionadores permitidos por arrendatario. Un valor negativo " "significa ilimitado." -msgid "" -"Number of seconds between sending events to nova if there are any events to " -"send." -msgstr "" -"Número de segundos entre en el envío de sucesos a nova si hay sucesos a " -"enviar." - msgid "Number of seconds to keep retrying to listen" msgstr "Número de segundos en seguir intentando escuchar" @@ -1420,13 +1233,6 @@ msgstr "" "Número de grupos de seguridad permitidos por arrendatario. Un valor negativo " "significa ilimitados." -msgid "" -"Number of security rules allowed per tenant. A negative value means " -"unlimited." -msgstr "" -"Número de reglas de seguridad permitidas por arrendatario. Un valor negativo " -"significa ilimitados." - msgid "Number of subnets allowed per tenant, A negative value means unlimited." msgstr "" "Número de subredes permitidas por arrendatario. Un valor negativo significa " @@ -1477,9 +1283,6 @@ msgid "Override the default dnsmasq settings with this file." msgstr "" "Alterar temporalmente los valores dnsmasq predeterminados con este archivo." -msgid "Owner type of the device: network/compute" -msgstr "Tipo de propietario del dispositivo: red/cálculo" - msgid "POST requests are not supported on this resource." msgstr "Las solicitudes de POST no son admitidas en este recurso." @@ -1515,9 +1318,6 @@ msgstr "" "Las opciones de actualización de fase no aceptan la especificación de " "revisión" -msgid "Ping timeout" -msgstr "Tiempo de espera de ping" - #, python-format msgid "Port %(id)s does not have fixed ip %(address)s" msgstr "El puerto %(id)s no tiene una IP fija %(address)s" @@ -1540,23 +1340,12 @@ msgstr "La delegación de prefijos sólo se puede utilizar con subredes IPv6." msgid "Private key of client certificate." msgstr "Clave privada del certificado de cliente." -#, python-format -msgid "Probe %s deleted" -msgstr "Se ha suprimido el analizador %s" - -#, python-format -msgid "Probe created : %s " -msgstr "Se ha creado analizador: %s " - msgid "Process is already started" msgstr "El proceso ya se ha iniciado" msgid "Process is not running." msgstr "El proceso no se está ejecutando." -msgid "Protocol to access nova metadata, http or https" -msgstr "El protocolo para acceder a los metadatos de Nova, http o https" - #, python-format msgid "Provider name %(name)s is limited by %(len)s characters" msgstr "El nombre de proveedor %(name)s está limitado a %(len)s caracteres" @@ -1611,28 +1400,6 @@ msgstr "" "El repositorio no contiene archivos HEAD para bifurcaciones de contratación " "y ampliación." -msgid "" -"Representing the resource type whose load is being reported by the agent. " -"This can be \"networks\", \"subnets\" or \"ports\". When specified (Default " -"is networks), the server will extract particular load sent as part of its " -"agent configuration object from the agent report state, which is the number " -"of resources being consumed, at every report_interval.dhcp_load_type can be " -"used in combination with network_scheduler_driver = neutron.scheduler." -"dhcp_agent_scheduler.WeightScheduler When the network_scheduler_driver is " -"WeightScheduler, dhcp_load_type can be configured to represent the choice " -"for the resource being balanced. Example: dhcp_load_type=networks" -msgstr "" -"Representando el tipo de recurso cuya carga está notificando el agente. " -"Puede ser \"networks\", \"subnets\" o \"ports\". Cuando se especifica (el " -"valor predeterminado es redes), el servidor extraerá la carga particular " -"enviada como parte del objeto de configuración de agentes desde el estado de " -"informe del agente, que es el número de recursos que se está consumiendo, en " -"cada report_interval.dhcp_load_type que puede utilizarse junto con " -"network_scheduler_driver = neutron.scheduler.dhcp_agent_scheduler." -"WeightScheduler. Cuando network_scheduler_driver es WeightScheduler, " -"dhcp_load_type se puede configurar para representar la opción para el " -"recurso que se está equilibrando. Ejemplo: dhcp_load_type=networks" - msgid "Request Failed: internal server error while processing your request." msgstr "" "Ha fallado la solicitar: error interno de servidor al procesar la solicitud." @@ -1712,14 +1479,6 @@ msgstr "" "Segundos entre nodos que informan del estado al servidor; debe ser menor que " "agent_down_time, mejor si es la mitad o menos que agent_down_time." -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 "" -"Segundos para considerar que el agente está inactivo; debe ser como mínimo " -"el doble de report_interval, para asegurarse de que el agente está inactivo " -"definitivamente." - #, python-format msgid "Security Group %(id)s %(reason)s." msgstr "Grupo de seguridad %(id)s %(reason)s." @@ -1758,16 +1517,6 @@ msgstr "" "Solo se admiten valores de protocolo %(values)s y representaciones de " "enteros [de 0 a 255]." -msgid "" -"Send notification to nova when port data (fixed_ips/floatingip) changes so " -"nova can update its cache." -msgstr "" -"Envíe notificación a nova cuando cambien los datos de puerto (fixed_ips/" -"floatingip) para que nova pueda actualizar la memoria caché." - -msgid "Send notification to nova when port status changes" -msgstr "Envíe notificación a nova cuando cambie el estado de puerto" - #, python-format msgid "" "Service provider '%(provider)s' could not be found for service type " @@ -1785,21 +1534,6 @@ msgstr "" "El tipo de servicio %(service_type)s no tiene un proveedor de servicio " "predeterminado" -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 "" -"Establecer el nuevo tiempo de espera en segundos para nuevas llamadas rpc " -"después de que el agente reciba SIGTERM. Si el valor se establece en 0, no " -"se modificará el tiempo de espera de rpc" - -msgid "" -"Set or un-set the don't fragment (DF) bit on outgoing IP packet carrying GRE/" -"VXLAN tunnel." -msgstr "" -"Establecer o anular el establecimiento del bit DF (don't fragment) en el " -"paquete de IP saliente que lleva el túnel GRE/VXLAN." - msgid "Shared address scope can't be unshared" msgstr "No se puede dejar de compartir el ámbito de la dirección compartida" @@ -1817,9 +1551,6 @@ msgstr "" msgid "Subnet pool has existing allocations" msgstr "La agrupación de subred tiene asignaciones existentes" -msgid "Subnet used for the l3 HA admin network." -msgstr "Subred utilizada con la red de administradores HA l3." - msgid "" "System-wide flag to determine the type of router that tenants can create. " "Only admin can override." @@ -1835,9 +1566,6 @@ msgstr "" msgid "TCP Port used by Nova metadata server." msgstr "Puerto TCP utilizado por el servidor de metadatos de Nova." -msgid "TTL for vxlan interface protocol packets." -msgstr "TTL para paquetes de protocolo de interfaz vxlan." - #, python-format msgid "Tag %(tag)s could not be found." msgstr "No se ha podido encontrar la etiqueta %(tag)s." @@ -1858,22 +1586,6 @@ msgstr "" "Nombre de inquilino para establecer conexión con el designado en el contexto " "de administración" -msgid "" -"The DHCP server can assist with providing metadata support on isolated " -"networks. Setting this value to True will cause the DHCP server to append " -"specific host routes to the DHCP request. The metadata service will only be " -"activated when the subnet does not contain any router port. The guest " -"instance must be configured to request host routes via DHCP (Option 121). " -"This option doesn't have any effect when force_metadata is set to True." -msgstr "" -"El servidor DHCP puede ajudar a proporcionar soporte para metadatos en " -"redes aisladas. Si se define este valor a True, provocará que el servidor " -"DHCP añada rutas específicas de host a la solicitud DHCP. El servicio de " -"metadatos sólo se activará cuando la subred no contenga ningún puerto de " -"direccionador. La instancia de invitado debe estar configurada para " -"solicitar rutas de host vía DHCP (Opción 121). Esta opción no tiene ningún " -"efecto cuando force_metadata está definido en True." - msgid "The UDP port to use for VXLAN tunnels." msgstr "El puerto UDP para a usar para los túneles VXLAN." @@ -1896,30 +1608,12 @@ msgstr "" "permanecerán sin cambios. Si el cuarto octeto no es 00, también se " "utilizará. Los otros se generan aleatoriamente. " -msgid "" -"The base mac address used for unique DVR instances by Neutron. The first 3 " -"octets will remain unchanged. If the 4th octet is not 00, it will also be " -"used. The others will be randomly generated. The 'dvr_base_mac' *must* be " -"different from 'base_mac' to avoid mixing them up with MAC's allocated for " -"tenant ports. A 4 octet example would be dvr_base_mac = fa:16:3f:4f:00:00. " -"The default is 3 octet" -msgstr "" -"Dirección mac base que Neutron utiliza para las instancias DVR exclusivas. " -"Los 3 primeros octetos permanecerán sin cambios. Si el cuarto octeto no es " -"00, también se utilizará. Los otros se generan aleatoriamente. " -"'dvr_base_mac' *debe* ser diferente de 'base_mac' para evitar que se mezclen " -"con MAC asignado para los puertos de arrendatarios. Un ejemplo de 4 octetos " -"sería dvr_base_mac = fa:16:3f:4f:00:00. El valor predeterminado es 3 octetos." - msgid "The core plugin Neutron will use" msgstr "El core plugin Neutron usará" msgid "The driver used to manage the DHCP server." msgstr "El controlador utilizado para gestionar el servidor DHCP." -msgid "The driver used to manage the virtual interface." -msgstr "El controlador utilizado para gestionar la interfaz virtual." - msgid "" "The email address to be used when creating PTR zones. If not specified, the " "email address will be admin@<dns_domain>" @@ -1928,55 +1622,15 @@ msgstr "" "especifica la dirección de correo electrónico será admin@<dns_domain>" msgid "" -"The maximum number of items returned in a single response, value was " -"'infinite' or negative integer means no limit" -msgstr "" -"El número máximo de elementos devueltos en una única respuesta, el valor " -"'infinite' o un entero negativo significa que no hay límite" - -msgid "" -"The network type to use when creating the HA network for an HA router. By " -"default or if empty, the first 'tenant_network_types' is used. This is " -"helpful when the VRRP traffic should use a specific network which is not the " -"default one." -msgstr "" -"Tipo de red que se debe utilizar al crear la red de alta disponibilidad para " -"un direccionador HA. De manera predeterminada o si está vacío, se utilizan " -"el primer 'tenant_network_types'. Esto es útil cuando el tráfico VRRP debe " -"utilizar una red específica que no sea el valor predeterminado." - -msgid "" "The number of seconds the agent will wait between polling for local device " "changes." msgstr "" "El número de segundos que el agente esperará entre sondeos de cambios de " "dispositivo local." -msgid "" -"The number of seconds to wait before respawning the ovsdb monitor after " -"losing communication with it." -msgstr "" -"Número de segundos a esperar antes de volver a generar el supervisor ovsdb " -"después de perder la comunicación con él." - msgid "The number of sort_keys and sort_dirs must be same" msgstr "El número de sort_keys y sort_dirs debe ser igual" -msgid "" -"The path for API extensions. Note that this can be a colon-separated list of " -"paths. For example: api_extensions_path = extensions:/path/to/more/exts:/" -"even/more/exts. The __path__ of neutron.extensions is appended to this, so " -"if your extensions are in there you don't need to specify them here." -msgstr "" -"La vía de acceso para ampliaciones de API. Observe que puede ser una lista " -"de vías de acceso separadas por punto y coma. Por ejemplo: " -"api_extensions_path = extensions:/path/to/more/exts:/even/more/exts. Además, " -"se añade __path__ of neutron.extensions, de forma que si sus extensiones " -"están ahí no es necesario especificarlas aquí." - -msgid "The physical network name with which the HA network can be created." -msgstr "Nombre de la red física con la que se puede crear la red HA." - #, python-format msgid "The port '%s' was deleted" msgstr "El puerto '%s' se ha suprimido" @@ -2031,14 +1685,6 @@ msgstr "El plugin ML2 necesita el valor de IP de túnel" msgid "Tunnel bridge to use." msgstr "Puente de túnel para utilizar." -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 "" -"Tipo de punto final de nova a utilizar. Este punto final se consultará en el " -"catálogo de keystone y debe ser uno de los siguientes: público, interno o " -"administrativo." - msgid "URL for connecting to designate" msgstr "URL para establecer conexión con el designado" @@ -2159,14 +1805,6 @@ msgid "Use either --delta or relative revision, not both" msgstr "Utilice --delta o la revisión relativa, pero no ambas" msgid "" -"Use ipset to speed-up the iptables based security groups. Enabling ipset " -"support requires that ipset is installed on L2 agent node." -msgstr "" -"Utilice ipset para agilizar los grupos de seguridad basados en iptables. " -"Para habilitar el soporte para ipset es necesario que ipset esté instalado " -"en el nodo agente L2." - -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." @@ -2216,62 +1854,15 @@ msgstr "" "QoS. Consulte el manual de tc-tbf para obtener más información." msgid "" -"When proxying metadata requests, Neutron signs the Instance-ID header with a " -"shared secret to prevent spoofing. You may select any string for a secret, " -"but it must match here and in the configuration used by the Nova Metadata " -"Server. NOTE: Nova uses the same config key, but in [neutron] section." -msgstr "" -"Cuando se envían solicitudes de metadatos por proxy, Neutron firma la " -"cabecera ID de instancia con un secreto compartido para evitar la " -"suplantación de identidad. Puede seleccionar cualquier cadena como secreto, " -"pero debe coincidir con la que se haya utilizado en la configuration del " -"servidor de metadatos de Nova. NOTA: Nova utiliza la misma clave de " -"configuración, pero en la sección [neutron]." - -msgid "" "Where to store Neutron state files. This directory must be writable by the " "agent." msgstr "" "Dónde almacenar archivos de estado Neutron. Este directorio se debe poder " "escribir por el agente." -msgid "" -"With IPv6, the network used for the external gateway does not need to have " -"an associated subnet, since the automatically assigned link-local address " -"(LLA) can be used. However, an IPv6 gateway address is needed for use as the " -"next-hop for the default route. If no IPv6 gateway address is configured " -"here, (and only then) the neutron router will be configured to get its " -"default route from router advertisements (RAs) from the upstream router; in " -"which case the upstream router must also be configured to send these RAs. " -"The ipv6_gateway, when configured, should be the LLA of the interface on the " -"upstream router. If a next-hop using a global unique address (GUA) is " -"desired, it needs to be done via a subnet allocated to the network and not " -"through this parameter. " -msgstr "" -"Con IPv6, la red utilizada para la pasarela externa no debetener una subred " -"asociada, ya que puede utilizarse la dirección de enlace local(LLA) asignada " -"automáticamente. No obstante, se necesita una dirección de pasarela IPv6 " -"parautilizarla como siguiente salto para la ruta predeterminada. Si no se " -"configura aquí ningunadirección de pasarela IPv6, (y sólo entonces) se " -"configurará un direccionador de Neutronpara obtener su ruta predeterminada " -"de los avisos de direccionador (RA) deldireccionador en sentido ascendente; " -"en este caso, el direccionador en sentido ascendente también " -"debeconfigurarse para enviar estos RA. ipv6_gateway, cuando se configurada, " -"debeser la LLA de interfaz en el direccionador en sentido ascendente. Si " -"desea un siguiente salto utilizando una dirección exclusivo global (GUA), " -"debe hacerse utilizando una subred asignada a la red, no mediante este " -"parámetro." - msgid "You must implement __call__" msgstr "Debe implementar __call__" -msgid "" -"You must provide a config file for bridge - either --config-file or " -"env[NEUTRON_TEST_CONFIG_FILE]" -msgstr "" -"Debe proporcionar un archivo config para puente, ya sea --config-file o " -"env[NEUTRON_TEST_CONFIG_FILE]" - msgid "You must provide a revision or relative delta" msgstr "Debe proporcionar una revisión o delta relativa" diff --git a/neutron/locale/fr/LC_MESSAGES/neutron.po b/neutron/locale/fr/LC_MESSAGES/neutron.po index 21d254a820..7ceaf0bab2 100644 --- a/neutron/locale/fr/LC_MESSAGES/neutron.po +++ b/neutron/locale/fr/LC_MESSAGES/neutron.po @@ -12,7 +12,7 @@ msgid "" msgstr "" "Project-Id-Version: neutron VERSION\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2023-01-26 15:02+0000\n" +"POT-Creation-Date: 2023-05-15 17:54+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -138,26 +138,10 @@ msgstr "Ajoute les attributs de test aux ressources principales." msgid "Agent %(id)s is not a L3 Agent or has been disabled" msgstr "L'agent %(id)s n'est pas un agent L3 ou a été désactivé" -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 agent " -"until admin changes admin_state_up to True." -msgstr "" -"L'agent démarre avec admin_state_up=False si enable_new_agents=False. Dans " -"ce cas, les ressources de l'utilisateur ne sont pas planifiées " -"automatiquement pour l'agent sauf si l'administrateur affecte la valeur True " -"à admin_state_up. " - #, python-format msgid "Agent updated: %(payload)s" msgstr "Mise à jour de l'agent: %(payload)s" -msgid "Allow auto scheduling networks to DHCP agent." -msgstr "Autorise la planification automatique des réseaux de l'agent DHCP." - -msgid "Allow auto scheduling of routers to L3 agent." -msgstr "Autorise la planification automatique des routeurs vers l'agent L3." - msgid "Allow running metadata proxy." msgstr "Autorisez le proxy de métadonnées en cours d'exécution." @@ -171,11 +155,6 @@ msgstr "Autoriser la création d'enregistrements PTR" msgid "Allow the usage of the bulk API" msgstr "Autoriser l'utilisation de l'API de traitement en bloc" -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" - msgid "" "Allows for serving metadata requests coming from a dedicated metadata access " "network whose CIDR is 169.254.169.254/16 (or larger prefix), and is " @@ -386,9 +365,6 @@ msgstr "" 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." - msgid "" "Comma-separated list of <network_device>:<vfs_to_exclude> tuples, mapping " "network_device to the agent's node-specific list of virtual functions that " @@ -453,27 +429,10 @@ msgstr "" "Liste séparée par des virgules des serveurs DNS qui seront utilisés comme " "réexpéditeurs." -msgid "Command to execute" -msgstr "Commande à exécuter" - -msgid "Config file for interface driver (You may also use l3_agent.ini)" -msgstr "" -"Fichier de configuration du pilote d'interface (vous pouvez aussi utiliser " -"l3_agent.ini)" - #, python-format msgid "Conflicting value ethertype %(ethertype)s for CIDR %(cidr)s" msgstr "Valeur en conflit ethertype %(ethertype)s pour le CIDR %(cidr)s" -msgid "" -"Controls whether the neutron security group API is enabled in the server. It " -"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." - #, python-format msgid "Could not bind to %(host)s:%(port)s after trying for %(time)d seconds" msgstr "" @@ -530,13 +489,6 @@ msgstr "" "Nombre par défaut d'entrées RBAC autorisées par locataire. Une valeur " "négative signifie que le nombre est illimité." -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 " -"négative signifie illimité." - msgid "Default security group" msgstr "Groupe de sécurité par défaut" @@ -611,23 +563,6 @@ 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" -msgid "Driver to use for scheduling network to DHCP agent" -msgstr "Pilote à utiliser pour la planification du réseau de 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" - -msgid "" -"Driver used for ipv6 prefix delegation. This needs to be an entry point " -"defined in the neutron.agent.linux.pd_drivers namespace. See setup.cfg for " -"entry points included with the neutron source." -msgstr "" -"Pilote utilisé pour la délégation de préfixe ipv6. Il doit s'agir d'un point " -"d'entrée défini dans l'espace de nom neutron.agent.linux.pd_drivers. Voir " -"setup.cfg pour connaître les points d'entrée inclus avec la source de " -"neutron. " - #, python-format msgid "" "Duplicate L3HARouterAgentPortBinding is created for router(s) %(router)s. " @@ -675,13 +610,6 @@ msgid "Enable SSL on the API server" msgstr "Active SSL sur le serveur API" msgid "" -"Enable VXLAN on the agent. Can be enabled when agent is managed by ml2 " -"plugin using linuxbridge mechanism driver" -msgstr "" -"Activer VXLAN sur l'agent. Il peut être activé lorsque l'agent est géré par " -"le plug-in ml2 utilisant le pilote de mécanisme linuxbridge" - -msgid "" "Enable services on an agent with admin_state_up False. If this option is " "False, when admin_state_up of an agent is turned False, services on it will " "be disabled. Agents with admin_state_up False are not selected for automatic " @@ -739,13 +667,6 @@ msgstr "" "Le pilote d'extension %(driver)s requis pour le plugin de service " "%(service_plugin)s est introuvable." -msgid "" -"Extension to use alongside ml2 plugin's l2population mechanism driver. It " -"enables the plugin to populate VXLAN forwarding table." -msgstr "" -"Extension à utiliser avec le pilote de mécanisme l2population du plug-in " -"ml2. Elle permet au plug-in de remplir la table de réacheminement VXLAN." - #, python-format msgid "Extension with alias %s does not exist" msgstr "L'extension avec l'alias %s n'existe pas" @@ -847,18 +768,6 @@ msgstr "" "Le code ICMP (port-range-max) %(value)s est fourni mais le type ICMP (port-" "range-min) est manquant." -msgid "ID of network" -msgstr "ID du réseau" - -msgid "ID of network to probe" -msgstr "ID du réseau à sonder" - -msgid "ID of probe port to delete" -msgstr "ID du port sonde à supprimer" - -msgid "ID of probe port to execute command" -msgstr "ID du port sonde pour exécuter la commande" - msgid "ID of the router" msgstr "Identifiant du routeur" @@ -922,19 +831,6 @@ msgid "Illegal IP version number" msgstr "Numéro de version IP illégal" msgid "" -"In some cases the Neutron router is not present to provide the metadata IP " -"but the DHCP server can be used to provide this info. Setting this value " -"will force the DHCP server to append specific host routes to the DHCP " -"request. If this option is set, then the metadata service will be activated " -"for all the networks." -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 " -"est définie, le service de métadonnées est activé pour tous les réseaux." - -msgid "" "Indicates that this L3 agent should also handle routers that do not have an " "external network gateway configured. This option should be True only for a " "single agent in a Neutron deployment, and may be False for all agents if all " @@ -975,12 +871,6 @@ msgstr "" msgid "Interface to monitor" msgstr "Interface à surveiller" -msgid "" -"Interval between checks of child process liveness (seconds), use 0 to disable" -msgstr "" -"Intervalle entre les vérifications de l'activité du processus enfant (en " -"secondes). Utilisez 0 pour désactiver" - msgid "Interval between two metering measures" msgstr "Intervalle entre deux mesures" @@ -1058,14 +948,6 @@ msgid "Invalid value for port %(port)s" msgstr "Valeur non valide pour le port %(port)s" msgid "" -"Iptables mangle mark used to mark ingress from external network. This mark " -"will be masked with 0xffff so that only the lower 16 bits will be used." -msgstr "" -"Marque Mangle Iptables utilisée pour marquer les entrées du réseau externe. " -"Cette marque sera masquée avec 0xffff de sorte que seuls les 16 bits les " -"plus bas soient utilisés. " - -msgid "" "Iptables mangle mark used to mark metadata valid requests. This mark will be " "masked with 0xffff so that only the lower 16 bits will be used." msgstr "" @@ -1124,12 +1006,6 @@ msgstr "Emplacement du socket de domaine UNIX du proxy de métadonnées" msgid "Location to store DHCP server config files." msgstr "Emplacement de stockage des fichiers de configuration du serveur DHCP." -msgid "Location to store IPv6 PD files." -msgstr "Emplacement pour stocker les fichiers IPv6 PD" - -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" @@ -1205,11 +1081,6 @@ msgstr "Pilote de décompte" msgid "MinRtrAdvInterval setting for radvd.conf" 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." - #, python-format msgid "Missing key in mapping: '%s'" msgstr "Clé manquante dans le mappage : '%s'" @@ -1224,22 +1095,6 @@ msgstr "" "multidiffusion. Dans le cas contraire, il désactive le mode VXLAN de " "multidiffusion." -msgid "" -"Multicast group(s) for vxlan interface. A range of group addresses may be " -"specified by using CIDR notation. Specifying a range allows different VNIs " -"to use different group addresses, reducing or eliminating spurious broadcast " -"traffic to the tunnel endpoints. To reserve a unique group for each possible " -"(24-bit) VNI, use a /8 such as 239.0.0.0/8. This setting must be the same on " -"all the agents." -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 " -"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." - #, python-format msgid "Multiple default providers for service %s" msgstr "Fournisseurs multiples par défaut pour le service %s" @@ -1264,11 +1119,6 @@ msgstr "" msgid "Name of Open vSwitch bridge to use" msgstr "Nom du pont Open vSwitch à utiliser" -msgid "" -"Name of nova region to use. Useful if keystone manages more than one region." -msgstr "" -"Nom de la région nova à utiliser. Utile si keystone gère plusieurs régions." - msgid "Namespace of the router" msgstr "Espace de nom du routeur" @@ -1347,16 +1197,6 @@ msgid "Not allowed to manually remove a router from an agent in 'dvr' mode." msgstr "" "Non autorisé à retirer manuellement un routeur d'un agent en mode 'dvr'." -msgid "" -"Number of DHCP agents scheduled to host a tenant network. If this number is " -"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 est supérieur à 1, le planificateur affecte automatiquement plusieurs " -"agents DHCP pour un réseau titulaire donné, ce qui fournit de la haute " -"disponibilité au service DHCP. " - 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 " @@ -1366,25 +1206,6 @@ msgid "Number of backlog requests to configure the socket with" msgstr "Nombre de demandes en attente avec lequel configurer le socket" msgid "" -"Number of bits in an ipv4 PTR zone that will be considered network prefix. " -"It has to align to byte boundary. Minimum value is 8. Maximum value is 24. " -"As a consequence, range of values is 8, 16 and 24" -msgstr "" -"Nombre de bits dans une zone PTR ipv4 qui fera office de préfixe réseau. " -"Doit s'aligner sur la frontière de bit. La valeur minimum est 8. La valeur " -"maximum est 24. Par conséquent, la plage de valeurs est 8, 16 et 24" - -msgid "" -"Number of bits in an ipv6 PTR zone that will be considered network prefix. " -"It has to align to nyble boundary. Minimum value is 4. Maximum value is 124. " -"As a consequence, range of values is 4, 8, 12, 16,..., 124" -msgstr "" -"Nombre de bits dans une zone PTR ipv6 qui fera office de préfixe réseau. " -"Doit s'aligner sur la frontière nyble. La valeur minimum est 4. La valeur " -"maximum est 124. Par conséquent, la plage de valeurs est 4, 8, 12, 16,..., " -"124" - -msgid "" "Number of floating IPs allowed per tenant. A negative value means unlimited." msgstr "" "Nombre d'adresses IP flottantes autorisées par locataire. Une valeur " @@ -1406,13 +1227,6 @@ msgstr "" "Nombre de routeurs autorisés par locataire. Une valeur négative signifie " "illimité" -msgid "" -"Number of seconds between sending events to nova if there are any events to " -"send." -msgstr "" -"Nombre de secondes entre deux envois d'événements à nova s'il y a des " -"événements à envoyer." - msgid "Number of seconds to keep retrying to listen" msgstr "Nombre de secondes a attendre avant d'essayer d'écouter à nouveau" @@ -1423,13 +1237,6 @@ msgstr "" "Nombre de groupes de sécurité autorisés par locataire. Une valeur négative " "signifie illimité." -msgid "" -"Number of security rules allowed per tenant. A negative value means " -"unlimited." -msgstr "" -"Nombre de règles de sécurité autorisées par locataire. Une valeur négative " -"signifie illimité." - 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 " @@ -1482,9 +1289,6 @@ msgstr "" msgid "Override the default dnsmasq settings with this file." msgstr "Remplacez les paramètres dnsmasq par défaut par ce fichier." -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." @@ -1520,9 +1324,6 @@ msgstr "" "Les options de mise à niveau de phase n'acceptent pas la spécification de " "révision" -msgid "Ping timeout" -msgstr "Délai d'expiration de la commande ping" - #, python-format msgid "Port %(id)s does not have fixed ip %(address)s" msgstr "Le port %(id)s ne dispose pas de l'adresse IP fixe %(address)s." @@ -1548,23 +1349,12 @@ msgstr "" msgid "Private key of client certificate." msgstr "Clé privée pour le certificat client." -#, python-format -msgid "Probe %s deleted" -msgstr "Sonde %s supprimée" - -#, python-format -msgid "Probe created : %s " -msgstr "Sonde créée : %s " - msgid "Process is already started" msgstr "Le processus est déjà démarré" msgid "Process is not running." msgstr "Le processus n'est pas en fonctionnement." -msgid "Protocol to access nova metadata, http or https" -msgstr "Protocole d'accès aux métadonnées de nova, HTTP ou https" - #, python-format msgid "Provider name %(name)s is limited by %(len)s characters" msgstr "Le nom de fournisseur %(name)s est limité à %(len)s caractères" @@ -1619,29 +1409,6 @@ msgstr "" "Le référentiel ne contient pas les fichiers HEAD pour les branches contract " "et expand." -msgid "" -"Representing the resource type whose load is being reported by the agent. " -"This can be \"networks\", \"subnets\" or \"ports\". When specified (Default " -"is networks), the server will extract particular load sent as part of its " -"agent configuration object from the agent report state, which is the number " -"of resources being consumed, at every report_interval.dhcp_load_type can be " -"used in combination with network_scheduler_driver = neutron.scheduler." -"dhcp_agent_scheduler.WeightScheduler When the network_scheduler_driver is " -"WeightScheduler, dhcp_load_type can be configured to represent the choice " -"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" - msgid "Request Failed: internal server error while processing your request." msgstr "" "Echec de la demande : erreur de serveur interne lors du traitement de votre " @@ -1723,14 +1490,6 @@ msgstr "" "être inférieure à agent_down_time, et au mieux, inférieure ou égale à la " "moitié de agent_down_time." -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é." - #, python-format msgid "Security Group %(id)s %(reason)s." msgstr "Groupe de sécurité %(id)s %(reason)s." @@ -1769,17 +1528,6 @@ msgstr "" "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." -msgid "" -"Send notification to nova when port data (fixed_ips/floatingip) changes so " -"nova can update its cache." -msgstr "" -"Envoyer une notification à nova lors de la modification des données de port " -"(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" - #, python-format msgid "" "Service provider '%(provider)s' could not be found for service type " @@ -1797,21 +1545,6 @@ msgstr "" "Le type de service %(service_type)s ne possède pas de fournisseur de " "services par défaut" -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é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." - msgid "Shared address scope can't be unshared" msgstr "Impossible d'annuler le partage d'une portée d'adresse partagée" @@ -1830,10 +1563,6 @@ msgstr "" msgid "Subnet pool has existing allocations" msgstr "Le pool de sous-réseau dispose d'allocations existantes" -msgid "Subnet used for the l3 HA admin network." -msgstr "" -"Sous-réseau utilisé pour le réseau administrateur haute disponibilité L3." - msgid "" "System-wide flag to determine the type of router that tenants can create. " "Only admin can override." @@ -1847,9 +1576,6 @@ msgstr "Port TCP utilisé par le proxy d'espace de nom de métadonnées Neutron" msgid "TCP Port used by Nova metadata server." msgstr "Port TCP utilisé par le serveur de métadonnées Nova" -msgid "TTL for vxlan interface protocol packets." -msgstr "Durée de vie pour les paquets du protocole d'interface vxlan." - #, python-format msgid "Tag %(tag)s could not be found." msgstr "Tag %(tag)s introuvable." @@ -1867,22 +1593,6 @@ msgid "Tenant name for connecting to designate in admin context" msgstr "" "Nom de locataire pour la connexion au réseau désigné dans un contexte admin" -msgid "" -"The DHCP server can assist with providing metadata support on isolated " -"networks. Setting this value to True will cause the DHCP server to append " -"specific host routes to the DHCP request. The metadata service will only be " -"activated when the subnet does not contain any router port. The guest " -"instance must be configured to request host routes via DHCP (Option 121). " -"This option doesn't have any effect when force_metadata is set to True." -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." - msgid "The UDP port to use for VXLAN tunnels." msgstr "Port UDP a utiliser pour les tunnels VXLAN." @@ -1905,30 +1615,12 @@ msgstr "" "octets demeurent 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." -msgid "" -"The base mac address used for unique DVR instances by Neutron. The first 3 " -"octets will remain unchanged. If the 4th octet is not 00, it will also be " -"used. The others will be randomly generated. The 'dvr_base_mac' *must* be " -"different from 'base_mac' to avoid mixing them up with MAC's allocated for " -"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. " -"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. " - msgid "The core plugin Neutron will use" msgstr "Le core plugin de Neutron va etre utiliser" msgid "The driver used to manage the DHCP server." msgstr "Pilote utilisé pour gérer le serveur DHCP" -msgid "The driver used to manage the virtual interface." -msgstr "Pilote utilisé pour gérer l'interface virtuelle" - msgid "" "The email address to be used when creating PTR zones. If not specified, the " "email address will be admin@<dns_domain>" @@ -1937,60 +1629,17 @@ msgstr "" "pas indiquée, il s'agira de l'adresse admin@<dns_domain>" 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é" - -msgid "" -"The network type to use when creating the HA network for an HA router. By " -"default or if empty, the first 'tenant_network_types' is used. This is " -"helpful when the VRRP traffic should use a specific network which is not the " -"default one." -msgstr "" -"Type de réseau à utiliser lors de la création du réseau haute disponibilité " -"pour un routeur haute disponibilité. Par défaut ou si cette zone est vide, " -"le premier élément 'tenant_network_types' est utilisé. Cela s'avère utile " -"lorsque le trafic VRRP doit utiliser un réseau spécifique différent de celui " -"défini par défaut. " - -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 " "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." - 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" -msgid "" -"The path for API extensions. Note that this can be a colon-separated list of " -"paths. For example: api_extensions_path = extensions:/path/to/more/exts:/" -"even/more/exts. The __path__ of neutron.extensions is appended to this, so " -"if your extensions are in there you don't need to specify them here." -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." - -msgid "The physical network name with which the HA network can be created." -msgstr "" -"Nom de réseau physique avec lequel le réseau haute disponibilité peut être " -"créé. " - #, python-format msgid "The port '%s' was deleted" msgstr "Le port '%s' a été supprimé" @@ -2047,13 +1696,6 @@ msgstr "Valeur IP de tunnel requise par le plug-in ML2" msgid "Tunnel bridge to use." msgstr "Pont de tunnel à utiliser." -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 "" -"Type de nœud final Nova à utiliser. Ce nœud final sera recherché dans le " -"catalogue Keystone et il doit être de type public, interne ou admin." - msgid "URL for connecting to designate" msgstr "URL pour la connexion au réseau désigné" @@ -2174,14 +1816,6 @@ msgstr "" "Utiliser soit un --delta, soit une révision relative, mais pas les deux" msgid "" -"Use ipset to speed-up the iptables based security groups. Enabling ipset " -"support requires that ipset is installed on L2 agent node." -msgstr "" -"Utiliser ipset pour accélérer les groupes de sécurité basés sur iptables. " -"L'activation du support ipset nécessite l'installation d'ipset sur le noeud " -"d'agent L2." - -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." @@ -2229,62 +1863,15 @@ msgstr "" "port avec QoS. Consultez le manuel tc-tbf pour plus d'informations." msgid "" -"When proxying metadata requests, Neutron signs the Instance-ID header with a " -"shared secret to prevent spoofing. You may select any string for a secret, " -"but it must match here and in the configuration used by the Nova Metadata " -"Server. NOTE: Nova uses the same config key, but in [neutron] section." -msgstr "" -"Lors de la mise en cache des demandes de métadonnées, Neutron signe l'en-" -"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 " -"dans la section [neutron]." - -msgid "" "Where to store Neutron state files. This directory must be writable by the " "agent." msgstr "" "Où stocker des fichiers d'état de Neutron. Ce répertoire doit être " "accessible en écriture par l'agent." -msgid "" -"With IPv6, the network used for the external gateway does not need to have " -"an associated subnet, since the automatically assigned link-local address " -"(LLA) can be used. However, an IPv6 gateway address is needed for use as the " -"next-hop for the default route. If no IPv6 gateway address is configured " -"here, (and only then) the neutron router will be configured to get its " -"default route from router advertisements (RAs) from the upstream router; in " -"which case the upstream router must also be configured to send these RAs. " -"The ipv6_gateway, when configured, should be the LLA of the interface on the " -"upstream router. If a next-hop using a global unique address (GUA) is " -"desired, it needs to be done via a subnet allocated to the network and not " -"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. " - msgid "You must implement __call__" msgstr "Vous devez implémenter __call__" -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]" - msgid "You must provide a revision or relative delta" msgstr "Vous devez fournir une révision ou un delta relatif." diff --git a/neutron/locale/it/LC_MESSAGES/neutron.po b/neutron/locale/it/LC_MESSAGES/neutron.po index edac64439b..b4768f4153 100644 --- a/neutron/locale/it/LC_MESSAGES/neutron.po +++ b/neutron/locale/it/LC_MESSAGES/neutron.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: neutron VERSION\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2023-01-26 15:02+0000\n" +"POT-Creation-Date: 2023-05-15 17:54+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -133,25 +133,10 @@ msgstr "Aggiunge gli attributi di test alle risorse principali." msgid "Agent %(id)s is not a L3 Agent or has been disabled" msgstr "L'agent %(id)s non è un agent L3 oppure è stato disabilitato" -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 agent " -"until admin changes admin_state_up to True." -msgstr "" -"L'agent inizia con admin_state_up=False quando enable_new_agents=False. In " -"tal caso, le risorse dell'utente non saranno pianificate automaticamente per " -"l'agent finché l'admin non modifica admin_state_up in True." - #, python-format msgid "Agent updated: %(payload)s" msgstr "Agent aggiornato: %(payload)s" -msgid "Allow auto scheduling networks to DHCP agent." -msgstr "Consenti pianificazione automatica delle reti nell'agent DHCP." - -msgid "Allow auto scheduling of routers to L3 agent." -msgstr "Consenti pianificazione automatica dei router nell'agent L3." - msgid "Allow running metadata proxy." msgstr "Consenti l'esecuzione del proxy di metadati." @@ -164,11 +149,6 @@ msgstr "Consenti la creazione di record PTR" msgid "Allow the usage of the bulk API" msgstr "Consenti l'utilizzo dell'API bulk" -msgid "Allow to perform insecure SSL (https) requests to nova metadata" -msgstr "" -"Consentire l'esecuzione di richieste SSL (https) non protette sui metadati " -"nova" - msgid "" "Allows for serving metadata requests coming from a dedicated metadata access " "network whose CIDR is 169.254.169.254/16 (or larger prefix), and is " @@ -375,9 +355,6 @@ msgstr "" msgid "Cleanup resources of a specific agent type only." msgstr "Ripulire solo le risorse di un tipo di agent specifico." -msgid "Client certificate for nova metadata api server." -msgstr "Certificato client per il server api dei metadati nova" - msgid "" "Comma-separated list of <network_device>:<vfs_to_exclude> tuples, mapping " "network_device to the agent's node-specific list of virtual functions that " @@ -440,27 +417,10 @@ msgstr "" "Elenco separato da virgole dei server DNS che verranno utilizzati come " "server di inoltro." -msgid "Command to execute" -msgstr "Comando da eseguire" - -msgid "Config file for interface driver (You may also use l3_agent.ini)" -msgstr "" -"File di configurazione per il driver di interfaccia (È possibile utilizzare " -"anche l3_agent.ini)" - #, python-format msgid "Conflicting value ethertype %(ethertype)s for CIDR %(cidr)s" msgstr "Valore ethertype %(ethertype)s in conflitto per CIDR %(cidr)s" -msgid "" -"Controls whether the neutron security group API is enabled in the server. It " -"should be false when using no security groups or using the nova security " -"group API." -msgstr "" -"Controlla se l'API del gruppo di sicurezza neutron è abilitata sul server. " -"Dovrebbe essere impostata su false quando non si utilizzano gruppi di " -"sicurezza o si utilizza l'API del gruppo di sicurezza nova." - #, python-format msgid "Could not bind to %(host)s:%(port)s after trying for %(time)d seconds" msgstr "" @@ -516,13 +476,6 @@ msgstr "" "Numero predefinito di voci RBAC consentite per titolare. Un valore negativo " "indica un numero illimitato." -msgid "" -"Default number of resource allowed per tenant. A negative value means " -"unlimited." -msgstr "" -"Numero predefinito di risorse consentite per tenant. Un valore negativo " -"indica un numero illimitato." - msgid "Default security group" msgstr "Gruppo di sicurezza predefinito" @@ -596,23 +549,6 @@ msgstr "Driver per l'integrazione DNS esterna." msgid "Driver for security groups firewall in the L2 agent" msgstr "Driver per il firewall dei gruppi di sicurezza nell'agent L2" -msgid "Driver to use for scheduling network to DHCP agent" -msgstr "Driver da utilizzare per la pianificazione della rete nell'agent DHCP" - -msgid "Driver to use for scheduling router to a default L3 agent" -msgstr "" -"Driver da utilizzare per la pianificazione del router nell'agent L3 " -"predefinito" - -msgid "" -"Driver used for ipv6 prefix delegation. This needs to be an entry point " -"defined in the neutron.agent.linux.pd_drivers namespace. See setup.cfg for " -"entry points included with the neutron source." -msgstr "" -"Il driver utilizzato per la delega prefisso ipv6. Deve essere un punto di " -"immissione definito nello spazio dei nomi neutron.agent.linux.pd_drivers. " -"Consultare setup.cfg per i punti di immissione inclusi con l'origine neutron." - #, python-format msgid "" "Duplicate L3HARouterAgentPortBinding is created for router(s) %(router)s. " @@ -658,13 +594,6 @@ msgid "Enable SSL on the API server" msgstr "Abilitazione di SSL sul server API" msgid "" -"Enable VXLAN on the agent. Can be enabled when agent is managed by ml2 " -"plugin using linuxbridge mechanism driver" -msgstr "" -"Abilitare VXLAN sull'agent. Può essere abilitata quando l'agent è gestito " -"dal plugin ml2 utilizzando il driver del meccanismo linuxbridge" - -msgid "" "Enable services on an agent with admin_state_up False. If this option is " "False, when admin_state_up of an agent is turned False, services on it will " "be disabled. Agents with admin_state_up False are not selected for automatic " @@ -720,13 +649,6 @@ msgstr "" "Driver di estensione %(driver)s richiesto per il plugin di servizio " "%(service_plugin)s non trovato." -msgid "" -"Extension to use alongside ml2 plugin's l2population mechanism driver. It " -"enables the plugin to populate VXLAN forwarding table." -msgstr "" -"Estensione per utilizzare insieme del driver del meccanismo l2population del " -"plugin m12. Essa abilita il plugin per popolare la tabella di inoltro VXLAN." - #, python-format msgid "Extension with alias %s does not exist" msgstr "L'estensione con alias %s non esiste" @@ -829,18 +751,6 @@ msgstr "" "Il codice ICMP (port-range-max) %(value)s è stato fornito, ma il tipo ICMP " "(port-range-min) manca." -msgid "ID of network" -msgstr "ID della rete" - -msgid "ID of network to probe" -msgstr "ID di rete per probe" - -msgid "ID of probe port to delete" -msgstr "ID della porta probe da eliminare" - -msgid "ID of probe port to execute command" -msgstr "ID della porta probe per eseguire il comando" - msgid "ID of the router" msgstr "ID del router" @@ -904,20 +814,6 @@ msgid "Illegal IP version number" msgstr "Numero della versione IP non valido" msgid "" -"In some cases the Neutron router is not present to provide the metadata IP " -"but the DHCP server can be used to provide this info. Setting this value " -"will force the DHCP server to append specific host routes to the DHCP " -"request. If this option is set, then the metadata service will be activated " -"for all the networks." -msgstr "" -"In alcuni casi il router Neutron non è presente per fornire l'IP dei " -"metadati ma il server DHCP può essere utilizzato per fornire queste " -"informazioni. L'impostazione di questo valore su True farà in modo che il " -"server DHCP aggiunga instradamenti host specifici alla richiesta DHCP. Se " -"questa opzione è impostata, il servizio di metadati verrà attivato per tutte " -"le reti." - -msgid "" "Indicates that this L3 agent should also handle routers that do not have an " "external network gateway configured. This option should be True only for a " "single agent in a Neutron deployment, and may be False for all agents if all " @@ -959,12 +855,6 @@ msgstr "" msgid "Interface to monitor" msgstr "Interfaccia da monitorare" -msgid "" -"Interval between checks of child process liveness (seconds), use 0 to disable" -msgstr "" -"Intervallo tra i controlli dell'attività del processo child (secondi), " -"utilizzare 0 per disabilitare" - msgid "Interval between two metering measures" msgstr "Intervallo tra due misure" @@ -1041,14 +931,6 @@ msgid "Invalid value for port %(port)s" msgstr "Valore invalido per la porta %(port)s" msgid "" -"Iptables mangle mark used to mark ingress from external network. This mark " -"will be masked with 0xffff so that only the lower 16 bits will be used." -msgstr "" -"Indicatore mangle iptables per contrassegnare l'ingresso dalla rete esterna. " -"Tale indicatoreverrà mascherato con 0xffff in modo che verranno utilizzati " -"solo i 16 bit inferiori. " - -msgid "" "Iptables mangle mark used to mark metadata valid requests. This mark will be " "masked with 0xffff so that only the lower 16 bits will be used." msgstr "" @@ -1107,12 +989,6 @@ msgstr "Ubicazione del socket del dominio UNIX del proxy di metadati" msgid "Location to store DHCP server config files." msgstr "Ubicazione per archiviare i file di configurazione del server DHCP." -msgid "Location to store IPv6 PD files." -msgstr "Ubicazione per archiviare i file PD IPv6." - -msgid "Location to store IPv6 RA config files" -msgstr "Ubicazione per memorizzare i file di configurazione IPv6 RA" - msgid "Location to store child pid files" msgstr "Ubicazione per archiviare i file pid dell'elemento child" @@ -1186,11 +1062,6 @@ msgstr "Driver di misurazione" msgid "MinRtrAdvInterval setting for radvd.conf" msgstr "Impostazione MinRtrAdvInterval per radvd.conf" -msgid "Minimize polling by monitoring ovsdb for interface changes." -msgstr "" -"Ridurre al minimo il polling controllando ovsdb per le modifiche " -"all'interfaccia." - #, python-format msgid "Missing key in mapping: '%s'" msgstr "Chiave mancante nell'associazione: '%s'" @@ -1204,22 +1075,6 @@ msgstr "" "traffico broadcast a questo gruppo multicast. Quando non configurato, " "disabilita la modalità multicast VXLAN." -msgid "" -"Multicast group(s) for vxlan interface. A range of group addresses may be " -"specified by using CIDR notation. Specifying a range allows different VNIs " -"to use different group addresses, reducing or eliminating spurious broadcast " -"traffic to the tunnel endpoints. To reserve a unique group for each possible " -"(24-bit) VNI, use a /8 such as 239.0.0.0/8. This setting must be the same on " -"all the agents." -msgstr "" -"Gruppo multicast per l'interfaccia vxlan. Un intervallo di indirizzi di " -"gruppo può essere specificato utilizzando la notazione CIDR. La definizione " -"di un intervallo consente a VNI diversi di utilizzare indirizzi di gruppo " -"diversi, riducendo o eliminando il traffico di broadcast spurio agli " -"endpoint del tunnel. Per riservare un gruppo univoco per ciascun VNI " -"possibile (24-bit), utilizzare /8, ad esempio, 239.0.0.0/8. Questa " -"impostazione deve essere la stessa su tutti gli agent." - #, python-format msgid "Multiple default providers for service %s" msgstr "Più provider predefiniti per il servizio %s" @@ -1245,12 +1100,6 @@ msgstr "" msgid "Name of Open vSwitch bridge to use" msgstr "Nome del bridge Open vSwitch da utilizzare" -msgid "" -"Name of nova region to use. Useful if keystone manages more than one region." -msgstr "" -"Nome della regione nova da utilizzare. Utile nel caso in cui keystone " -"gestisce più di una regione." - msgid "Namespace of the router" msgstr "Spazio dei nomi del router" @@ -1330,16 +1179,6 @@ msgstr "" "Attualmente non è consentito rimuovere manualmente un router da un agent in " "modalità 'dvr'." -msgid "" -"Number of DHCP agents scheduled to host a tenant network. If this number is " -"greater than 1, the scheduler automatically assigns multiple DHCP agents for " -"a given tenant network, providing high availability for DHCP service." -msgstr "" -"Numero di agent DHCP pianificati per ospitare una rete titolare. Se questo " -"numero è maggiore di 1, lo scheduler assegna automaticamente più agent DHCP " -"per una data rete titolare, fornendo l'alta disponibilità per il servizio " -"DHCP." - msgid "Number of backlog requests to configure the metadata server socket with" msgstr "" "Numero di richieste di backlog con cui configurare il socket server dei " @@ -1349,25 +1188,6 @@ msgid "Number of backlog requests to configure the socket with" msgstr "Numero di richieste di backlog per configurare il socket con" msgid "" -"Number of bits in an ipv4 PTR zone that will be considered network prefix. " -"It has to align to byte boundary. Minimum value is 8. Maximum value is 24. " -"As a consequence, range of values is 8, 16 and 24" -msgstr "" -"Il numero di bit in una zona PTR ipv4 che verrà considerato prefisso di " -"rete. Deve allinearsi al limite di byte. Il valore minimo è 8. Il valore " -"massimo è 24. Di conseguenza, l'intervallo di valori è 8, 16 e 24" - -msgid "" -"Number of bits in an ipv6 PTR zone that will be considered network prefix. " -"It has to align to nyble boundary. Minimum value is 4. Maximum value is 124. " -"As a consequence, range of values is 4, 8, 12, 16,..., 124" -msgstr "" -"Il numero di bit in una zona PTR ipv6 che verrà considerato prefisso di " -"rete. Deve allinearsi al limite nyble. Il valore minimo è 4. Il valore " -"massimo è 124. Di conseguenza, l'intervallo di valori è 4, 8, 12, 16, ...., " -"124" - -msgid "" "Number of floating IPs allowed per tenant. A negative value means unlimited." msgstr "" "Numero di IP mobili consentiti per tenant. Un valore negativo indica un " @@ -1389,13 +1209,6 @@ msgstr "" "Numero di router consentiti per tenant. Un valore negativo indica un numero " "illimitato." -msgid "" -"Number of seconds between sending events to nova if there are any events to " -"send." -msgstr "" -"Numero di secondi tra l'invio di eventi a nova se vi sono eventuali eventi " -"da inviare." - msgid "Number of seconds to keep retrying to listen" msgstr "Numero di secondi per trattenere i nuovi tentativi di ascolto" @@ -1406,13 +1219,6 @@ msgstr "" "Numero di gruppi di sicurezza consentiti per tenant. Un valore negativo " "indica un numero illimitato." -msgid "" -"Number of security rules allowed per tenant. A negative value means " -"unlimited." -msgstr "" -"Numero di regole di sicurezza consentite per tenant. Un valore negativo " -"indica un numero illimitato." - msgid "Number of subnets allowed per tenant, A negative value means unlimited." msgstr "" "Numero di sottoreti consentite per tenant. Un valore negativo indica un " @@ -1464,9 +1270,6 @@ msgid "Override the default dnsmasq settings with this file." msgstr "" "Sostituire le impostazioni dnsmasq predefinite utilizzando questo file." -msgid "Owner type of the device: network/compute" -msgstr "Tipo proprietario dell'unità: rete/compute" - msgid "POST requests are not supported on this resource." msgstr "Le richieste POST non sono supportate su questa risorsa." @@ -1497,9 +1300,6 @@ msgid "Phase upgrade options do not accept revision specification" msgstr "" "Le opzioni di aggiornamento fase non accettano la specifica di revisione" -msgid "Ping timeout" -msgstr "Timeout di ping" - #, python-format msgid "Port %(id)s does not have fixed ip %(address)s" msgstr "La porta %(id)s non dispone di un ip fisso %(address)s" @@ -1522,23 +1322,12 @@ msgstr "La delega prefisso può essere utilizzata solo con sottoreti IPv6." msgid "Private key of client certificate." msgstr "Chiave privata del certificato client." -#, python-format -msgid "Probe %s deleted" -msgstr "Probe %s eliminato" - -#, python-format -msgid "Probe created : %s " -msgstr "Probe creato : %s " - msgid "Process is already started" msgstr "Processo già avviato" msgid "Process is not running." msgstr "Il processo non è in esecuzione." -msgid "Protocol to access nova metadata, http or https" -msgstr "Protocollo per accedere ai metadati nova, http o https" - #, python-format msgid "Provider name %(name)s is limited by %(len)s characters" msgstr "Il nome del provider %(name)s è limitato a %(len)s caratteri" @@ -1590,29 +1379,6 @@ msgid "" msgstr "" "Il repository non contiene i file HEAD per i rami di contratto ed espansione." -msgid "" -"Representing the resource type whose load is being reported by the agent. " -"This can be \"networks\", \"subnets\" or \"ports\". When specified (Default " -"is networks), the server will extract particular load sent as part of its " -"agent configuration object from the agent report state, which is the number " -"of resources being consumed, at every report_interval.dhcp_load_type can be " -"used in combination with network_scheduler_driver = neutron.scheduler." -"dhcp_agent_scheduler.WeightScheduler When the network_scheduler_driver is " -"WeightScheduler, dhcp_load_type can be configured to represent the choice " -"for the resource being balanced. Example: dhcp_load_type=networks" -msgstr "" -"Rappresentazione del tipo di risorsa il cui carico è segnalato dall'agent. " -"Può essere \"networks\", \"subnets\" o \"ports\". Quando specificato " -"(L'impostazione predefinita è networks), il server estrarrà il carico " -"particolare inviato come parte del relativo oggetto di configurazione agent " -"dallo stato del report agent, il quale rappresenta il numero di risorse " -"utilizzate, ad ogni report_interval. dhcp_load_type può essere utilizzato in " -"combinazione con network_scheduler_driver = neutron.scheduler." -"dhcp_agent_scheduler.WeightScheduler Quando network_scheduler_driver è " -"WeightScheduler, dhcp_load_type può essere configurato per rappresentare la " -"scelta per la risorsa in fase di bilanciamento. Esempio: " -"dhcp_load_type=networks" - msgid "Request Failed: internal server error while processing your request." msgstr "" "Richiesta non riuscita: errore server interno durante l'elaborazione della " @@ -1693,13 +1459,6 @@ msgstr "" "Secondi tra lo stato riportato dai nodi al server; deve essere inferiore di " "agent_down_time, è preferibile che sia la metà o meno di agent_down_time." -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 "" -"Secondi per considerare che l'agent è inattivo; deve essere almeno il doppio " -"di report_interval, per essere sicuri che l'agent è definitivamente inattivo." - #, python-format msgid "Security Group %(id)s %(reason)s." msgstr "Gruppo di sicurezza %(id)s %(reason)s." @@ -1738,16 +1497,6 @@ msgstr "" "supportato. Solo i valori del protocollo %(values)s e le rappresentazioni " "numeri interi [0-255] sono supportati." -msgid "" -"Send notification to nova when port data (fixed_ips/floatingip) changes so " -"nova can update its cache." -msgstr "" -"Invia una notifica a nova quando i dati porta (fixed_ips/floatingip) vengono " -"modificati e in tal modo nova può aggiornare la propria cache." - -msgid "Send notification to nova when port status changes" -msgstr "Invia una notifica a nova quando lo stato della porta cambia" - #, python-format msgid "" "Service provider '%(provider)s' could not be found for service type " @@ -1765,21 +1514,6 @@ msgstr "" "Il tipo del servizio %(service_type)s non ha un provider del servizio " "predefinito" -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 "" -"Impostare il nuovo timeout in secondi per le nuove chiamate rpc dopo che " -"l'agent riceve SIGTERM. Se il valore è impostato su 0, il timeout rpc non " -"verrà modificato" - -msgid "" -"Set or un-set the don't fragment (DF) bit on outgoing IP packet carrying GRE/" -"VXLAN tunnel." -msgstr "" -"Impostare o annullare l'impostazione del bit del frammento non DF sul " -"pacchetto IP in uscita che trasporta il tunnel GRE/VXLAN." - msgid "Shared address scope can't be unshared" msgstr "Impossibile annullare la condivisione di un ambito indirizzo condiviso" @@ -1796,9 +1530,6 @@ msgstr "La sottorete per l'interfaccia del router deve avere un IP gateway" msgid "Subnet pool has existing allocations" msgstr "Il pool di sottoreti ha assegnazioni esistenti" -msgid "Subnet used for the l3 HA admin network." -msgstr "Sottorete utilizzata per la rete admin HA L3" - msgid "" "System-wide flag to determine the type of router that tenants can create. " "Only admin can override." @@ -1812,9 +1543,6 @@ msgstr "Porta TCP utilizzata dal proxy spazio dei nomi dei metadati Neutron." msgid "TCP Port used by Nova metadata server." msgstr "Porta TCP utilizzata dal server di metadati Nova." -msgid "TTL for vxlan interface protocol packets." -msgstr "Pacchetti del protocollo dell'interfaccia TTL per vxlan." - #, python-format msgid "Tag %(tag)s could not be found." msgstr "Impossibile trovare il tag %(tag)s." @@ -1830,22 +1558,6 @@ msgstr "ID tenant per la connessione da designare nel contesto admin" msgid "Tenant name for connecting to designate in admin context" msgstr "Nome tenant per la connessione da designare nel contesto admin" -msgid "" -"The DHCP server can assist with providing metadata support on isolated " -"networks. Setting this value to True will cause the DHCP server to append " -"specific host routes to the DHCP request. The metadata service will only be " -"activated when the subnet does not contain any router port. The guest " -"instance must be configured to request host routes via DHCP (Option 121). " -"This option doesn't have any effect when force_metadata is set to True." -msgstr "" -"Il server DHCP può fornire il supporto di metadati nelle reti isolate. " -"L'impostazione di questo valore su True farà in modo che il server DHCP " -"aggiunga instradamenti host specifici alla richiesta DHCP. Il servizio di " -"metadati verrà attivato solo quando la sottorete non contiene porte del " -"router. L'istanza guest deve essere configurata per richiedere gli " -"instradamenti host mediante DHCP (Opzione 121). Questa opzione non ha alcun " -"effetto quando force_metadata è impostato su True." - msgid "The UDP port to use for VXLAN tunnels." msgstr "La porta UDP da utilizzare per i tunnel VXLAN." @@ -1868,30 +1580,12 @@ msgstr "" "rimangono inalterati. Se il quarto ottetto non è 00, potrà anche essere " "utilizzato. Gli altri vengono generati casualmente. " -msgid "" -"The base mac address used for unique DVR instances by Neutron. The first 3 " -"octets will remain unchanged. If the 4th octet is not 00, it will also be " -"used. The others will be randomly generated. The 'dvr_base_mac' *must* be " -"different from 'base_mac' to avoid mixing them up with MAC's allocated for " -"tenant ports. A 4 octet example would be dvr_base_mac = fa:16:3f:4f:00:00. " -"The default is 3 octet" -msgstr "" -"L'indirizzo mac di base utilizzato per istanze DVR univoche da Neutron. I " -"primi 3 ottetti rimangono inalterati. Se il quarto ottetto non è 00, potrà " -"anche essere utilizzato. Gli altri vengono generati casualmente. " -"'dvr_base_mac' *deve* essere diverso da 'base_mac' per evitare la confusione " -"con i MAC assegnati per le porte titolari. Un esempio di 4 ottetti è " -"dvr_base_mac = fa:16:3f:4f:00:00. Il valore predefinito è 3 ottetti" - msgid "The core plugin Neutron will use" msgstr "Il plugin principale che Neutron utilizzerà" msgid "The driver used to manage the DHCP server." msgstr "Il driver utilizzato per gestire il server DHCP." -msgid "The driver used to manage the virtual interface." -msgstr "Il driver utilizzato per gestire l'interfaccia virtuale." - msgid "" "The email address to be used when creating PTR zones. If not specified, the " "email address will be admin@<dns_domain>" @@ -1900,55 +1594,15 @@ msgstr "" "specificato, l'indirizzo email sarà admin@<dns_domain>" msgid "" -"The maximum number of items returned in a single response, value was " -"'infinite' or negative integer means no limit" -msgstr "" -"Il numero massimo di elementi restituiti in una singola risposta, il valore " -"era 'infinite' oppure un numero intero negativo che indica nessun limite" - -msgid "" -"The network type to use when creating the HA network for an HA router. By " -"default or if empty, the first 'tenant_network_types' is used. This is " -"helpful when the VRRP traffic should use a specific network which is not the " -"default one." -msgstr "" -"Il tipo di rete da utilizzare quando si crea la rete HA per un router HA. " -"Per impostazione predefinita o se vuoto, è utilizzato il primo " -"'tenant_network_types'. Ciò è utile quando il traffico VRRP deve utilizzare " -"una rete specifica che non è quella predefinita." - -msgid "" "The number of seconds the agent will wait between polling for local device " "changes." msgstr "" "Il numero di secondi in l'agent attenderà tra i polling per le modifiche " "dell'unità locale." -msgid "" -"The number of seconds to wait before respawning the ovsdb monitor after " -"losing communication with it." -msgstr "" -"Il numero di secondi di attesa prima di generare nuovamente il monitor ovsdb " -"dopo la perdita di comunicazione." - msgid "The number of sort_keys and sort_dirs must be same" msgstr "Il numero di sort_keys e sort_dirs deve essere uguale" -msgid "" -"The path for API extensions. Note that this can be a colon-separated list of " -"paths. For example: api_extensions_path = extensions:/path/to/more/exts:/" -"even/more/exts. The __path__ of neutron.extensions is appended to this, so " -"if your extensions are in there you don't need to specify them here." -msgstr "" -"Il percorso per le estensioni API. Può essere un elenco di percorsi separato " -"dai due punti. Ad esempio: api_extensions_path = extensions:/path/to/more/" -"exts:/even/more/exts. Il __percorso__ di neutron.extensions è aggiunto a " -"tale percorso, per cui, se le estensioni si trovano nel percorso non è " -"necessario specificarle." - -msgid "The physical network name with which the HA network can be created." -msgstr "Il nome della rete fisica con cui può essere creata la rete HA." - #, python-format msgid "The port '%s' was deleted" msgstr "La porta '%s' è stata eliminata" @@ -2004,13 +1658,6 @@ msgstr "Valore IP tunnel IP richiesto dal plugin ML2" msgid "Tunnel bridge to use." msgstr "Bridge del tunnel da utilizzare." -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 "" -"Tipo di endpoint nova da utilizzare. Questo endpoint verrà ricercato nel " -"catalogo keystone e deve essere public, internal o admin." - msgid "URL for connecting to designate" msgstr "URL per la connessione da designare" @@ -2131,14 +1778,6 @@ msgid "Use either --delta or relative revision, not both" msgstr "Utilizzare --revisione delta o relativa, non entrambe" msgid "" -"Use ipset to speed-up the iptables based security groups. Enabling ipset " -"support requires that ipset is installed on L2 agent node." -msgstr "" -"Utilizzare ipset per velocizzare i gruppi di sicurezza basati su iptable. " -"L'abilitazione del supporto ipset richiede che ipset sia installato sul nodo " -"dell'agent L2." - -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." @@ -2187,61 +1826,15 @@ msgstr "" "porta con QoS. Per ulteriori informazioni, vedere il manuale tc-tbf." msgid "" -"When proxying metadata requests, Neutron signs the Instance-ID header with a " -"shared secret to prevent spoofing. You may select any string for a secret, " -"but it must match here and in the configuration used by the Nova Metadata " -"Server. NOTE: Nova uses the same config key, but in [neutron] section." -msgstr "" -"Quando si trasferiscono richieste di metadati, Neutron firma l'intestazione " -"Instance-ID con un segreto condiviso per evitare lo spoofing. È possibile " -"selezionare una qualsiasi stringa per un segreto ma deve corrispondere qui e " -"nella configurazione utilizzata da Nova Metadata Server. NOTA: Nova utilizza " -"la stessa chiave di configurazione, ma nella sezione [neutron]." - -msgid "" "Where to store Neutron state files. This directory must be writable by the " "agent." msgstr "" "Dove memorizzare i file di stato Neutron. Questa directory deve essere " "scrivibile dall'agent." -msgid "" -"With IPv6, the network used for the external gateway does not need to have " -"an associated subnet, since the automatically assigned link-local address " -"(LLA) can be used. However, an IPv6 gateway address is needed for use as the " -"next-hop for the default route. If no IPv6 gateway address is configured " -"here, (and only then) the neutron router will be configured to get its " -"default route from router advertisements (RAs) from the upstream router; in " -"which case the upstream router must also be configured to send these RAs. " -"The ipv6_gateway, when configured, should be the LLA of the interface on the " -"upstream router. If a next-hop using a global unique address (GUA) is " -"desired, it needs to be done via a subnet allocated to the network and not " -"through this parameter. " -msgstr "" -"Con IPv6, non è necessario che la rete utilizzata per il gateway esterno " -"disponga di una sottorete associata, poiché verrà utilizzato il LLA (link-" -"local address) assegnato automaticamente. Tuttavia, è necessario un " -"indirizzo gateway IPv6 per l'utilizzo come successivo hop per " -"l'instradamento predefinito. Se qui non è configuratonessun indirizzo " -"gateway Ipv6 (e solo poi) verrà configurato il router Neutron per ottenere " -"il relativo instradamento predefinito da RA (Router Advertisement) dal " -"router upstream; in tal caso il router upstream deve essere anche " -"configuratoper inviare questi RA. Ipv6_gateway, quando configurato, " -"deveessere il LLA dell'interfaccia sul router upstream. Se si desidera un " -"hop successivo che utilizzi un GUA (Global Uunique Address) è necessario " -"ottenerlo mediante una sottorete assegnata alla rete e non attraverso questo " -"parametro." - msgid "You must implement __call__" msgstr "È necessario implementare __call__" -msgid "" -"You must provide a config file for bridge - either --config-file or " -"env[NEUTRON_TEST_CONFIG_FILE]" -msgstr "" -"È necessario fornire un file di configurazione per il bridge - --config-file " -"o env[NEUTRON_TEST_CONFIG_FILE]" - msgid "You must provide a revision or relative delta" msgstr "È necessario fornire una revisione o delta relativo" diff --git a/neutron/locale/ja/LC_MESSAGES/neutron.po b/neutron/locale/ja/LC_MESSAGES/neutron.po index 0e94292e47..387075add3 100644 --- a/neutron/locale/ja/LC_MESSAGES/neutron.po +++ b/neutron/locale/ja/LC_MESSAGES/neutron.po @@ -17,7 +17,7 @@ msgid "" msgstr "" "Project-Id-Version: neutron VERSION\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2023-01-26 15:02+0000\n" +"POT-Creation-Date: 2023-05-15 17:54+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -143,27 +143,10 @@ msgid "Agent %(id)s is not a L3 Agent or has been disabled" msgstr "" "エージェント %(id)s は、L3 エージェントでないか、使用不可になっています" -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 agent " -"until admin changes admin_state_up to True." -msgstr "" -"enable_new_agents=False の場合、エージェントは admin_state_up=False の状態で" -"処理を開始します。この場合、 管理者が admin_state_up を True に変更するまで、" -"ユーザーのリソースが自動的にエージェントにスケジュール設定されることはありま" -"せん。" - #, python-format msgid "Agent updated: %(payload)s" msgstr "エージェントが更新されました: %(payload)s" -msgid "Allow auto scheduling networks to DHCP agent." -msgstr "DHCP エージェントに対するネットワークの自動スケジューリングを許可" - -msgid "Allow auto scheduling of routers to L3 agent." -msgstr "" -"L3 エージェントに対するルーターの自動スケジューリングを許可してください。" - msgid "Allow running metadata proxy." msgstr "メタデータプロキシーの実行を許可します。" @@ -176,11 +159,6 @@ msgstr "PTR レコードの作成の許可" msgid "Allow the usage of the bulk API" msgstr "Bulk API の使用を許可" -msgid "Allow to perform insecure SSL (https) requests to nova metadata" -msgstr "" -"Nova メタデータに対する非セキュアな SSL (https) 要求を実行することを許可しま" -"す" - msgid "" "Allows for serving metadata requests coming from a dedicated metadata access " "network whose CIDR is 169.254.169.254/16 (or larger prefix), and is " @@ -385,9 +363,6 @@ msgstr "" msgid "Cleanup resources of a specific agent type only." msgstr "特定のエージェントタイプのみのリソースをクリーンアップします。" -msgid "Client certificate for nova metadata api server." -msgstr "Nova メタデータ API サーバー用のクライアント証明書。" - msgid "" "Comma-separated list of <network_device>:<vfs_to_exclude> tuples, mapping " "network_device to the agent's node-specific list of virtual functions that " @@ -448,27 +423,10 @@ msgid "" "Comma-separated list of the DNS servers which will be used as forwarders." msgstr "フォワーダーとして使用される DNS サーバーのカンマ区切りのリスト。" -msgid "Command to execute" -msgstr "実行するコマンド" - -msgid "Config file for interface driver (You may also use l3_agent.ini)" -msgstr "" -"インターフェースドライバーの構成ファイル (l3_agent.ini を使用することもできま" -"す)" - #, python-format msgid "Conflicting value ethertype %(ethertype)s for CIDR %(cidr)s" msgstr "CIDR %(cidr)s とイーサネットタイプ値 %(ethertype)s が競合しています" -msgid "" -"Controls whether the neutron security group API is enabled in the server. It " -"should be false when using no security groups or using the nova security " -"group API." -msgstr "" -"Neutron セキュリティーグループ API をサーバーで有効化するかどうかを制御しま" -"す。セキュリティーグループを使用しない場合、または Nova セキュリティーグルー" -"プ API を使用する場合には、False にする必要があります。" - #, python-format msgid "Could not bind to %(host)s:%(port)s after trying for %(time)d seconds" msgstr "" @@ -521,13 +479,6 @@ msgstr "" "テナントごとの RBAC 項目のデフォルト数。負の値がある場合、制限が設定されてい" "ないことを指します。" -msgid "" -"Default number of resource allowed per tenant. A negative value means " -"unlimited." -msgstr "" -"テナント当たりに許可されるリソースのデフォルト数。負の値は無制限を意味しま" -"す。" - msgid "Default security group" msgstr "デフォルトセキュリティグループ" @@ -600,25 +551,6 @@ msgstr "外部 DNS の連携のためのドライバー。" msgid "Driver for security groups firewall in the L2 agent" msgstr "L2 エージェントのセキュリティーグループのファイアウォールのドライバー" -msgid "Driver to use for scheduling network to DHCP agent" -msgstr "" -"DHCP エージェントに対するネットワークのスケジューリングに使用するドライバー" - -msgid "Driver to use for scheduling router to a default L3 agent" -msgstr "" -"デフォルトの L3 エージェントに対するルーターのスケジューリングに使用するドラ" -"イバー" - -msgid "" -"Driver used for ipv6 prefix delegation. This needs to be an entry point " -"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 の名前空間で定義したエントリーポイントである必要があります。" -"neutron のソースに含まれるエントリーポイントについては、setup.cfg を参照して" -"ください。" - #, python-format msgid "" "Duplicate L3HARouterAgentPortBinding is created for router(s) %(router)s. " @@ -663,14 +595,6 @@ msgid "Enable SSL on the API server" msgstr "API サーバー上で SSL を有効にします" msgid "" -"Enable VXLAN on the agent. Can be enabled when agent is managed by ml2 " -"plugin using linuxbridge mechanism driver" -msgstr "" -"エージェントで VXLAN を有効にしてください。linuxbridge メカニズムドライバーを" -"使用してエージェントが ml2 プラグインによって管理されているときに、VXLAN を有" -"効にできます" - -msgid "" "Enable services on an agent with admin_state_up False. If this option is " "False, when admin_state_up of an agent is turned False, services on it will " "be disabled. Agents with admin_state_up False are not selected for automatic " @@ -725,14 +649,6 @@ msgstr "" "サービスプラグイン %(service_plugin)s に必要な拡張ドライバー %(driver)s が見" "つかりませんでした。" -msgid "" -"Extension to use alongside ml2 plugin's l2population mechanism driver. It " -"enables the plugin to populate VXLAN forwarding table." -msgstr "" -"ml2 プラグインの l2population メカニズムドライバーとともに使用する拡張機能。" -"これにより、このプラグインは VXLAN 転送テーブルにデータを追加できるようになり" -"ます。" - #, python-format msgid "Extension with alias %s does not exist" msgstr "エイリアス %s を持つ拡張は存在しません" @@ -836,18 +752,6 @@ msgstr "" "ICMP コード (port-range-max) %(value)s が指定されましたが、ICMP タイプ (port-" "range-min) がありません。" -msgid "ID of network" -msgstr "ネットワークの ID" - -msgid "ID of network to probe" -msgstr "プローブするネットワークの ID" - -msgid "ID of probe port to delete" -msgstr "削除するプローブポートの ID" - -msgid "ID of probe port to execute command" -msgstr "コマンドを実行するプローブ ポートの ID" - msgid "ID of the router" msgstr "ルーターの ID" @@ -911,18 +815,6 @@ msgid "Illegal IP version number" msgstr "IP バージョン番号が正しくありません" msgid "" -"In some cases the Neutron router is not present to provide the metadata IP " -"but the DHCP server can be used to provide this info. Setting this value " -"will force the DHCP server to append specific host routes to the DHCP " -"request. If this option is set, then the metadata service will be activated " -"for all the networks." -msgstr "" -"Neutron ルーターが存在せず、メタデータ IP を提供できない場合に、DHCP サーバー" -"を使用してこの情報を提供することができます。この値を設定すると、DHCP サーバー" -"は DHCP 要求に対して特定のホストの経路を追加します。このオプションを設定する" -"と、すべてのネットワークに対してメタデータサービスが有効化されます。" - -msgid "" "Indicates that this L3 agent should also handle routers that do not have an " "external network gateway configured. This option should be True only for a " "single agent in a Neutron deployment, and may be False for all agents if all " @@ -963,10 +855,6 @@ msgstr "" msgid "Interface to monitor" msgstr "モニター対象のインターフェース" -msgid "" -"Interval between checks of child process liveness (seconds), use 0 to disable" -msgstr "子プロセスの動作状況を確認する間隔 (秒)、無効にするには 0 を指定します" - msgid "Interval between two metering measures" msgstr "2 つの計測間の間隔" @@ -1042,14 +930,6 @@ msgid "Invalid value for port %(port)s" msgstr "ポート %(port)s の無効値" msgid "" -"Iptables mangle mark used to mark ingress from external network. This mark " -"will be masked with 0xffff so that only the lower 16 bits will be used." -msgstr "" -"Iptables は外部ネットワークからの進入を示すために使用されるマークを分割しま" -"す。このマークを 0xffff でマスキングすることで、後半の 16 ビットのみを使用し" -"ます。" - -msgid "" "Iptables mangle mark used to mark metadata valid requests. This mark will be " "masked with 0xffff so that only the lower 16 bits will be used." msgstr "" @@ -1105,12 +985,6 @@ msgstr "メタデータプロキシーの UNIX ドメインソケットの場所 msgid "Location to store DHCP server config files." msgstr "DHCP サーバーの構成ファイルを保存するロケーション。" -msgid "Location to store IPv6 PD files." -msgstr "IPv6 PD ファイルを保存するロケーション。" - -msgid "Location to store IPv6 RA config files" -msgstr "IPv6 RA 設定ファイルを保存する場所" - msgid "Location to store child pid files" msgstr "子プロセスの PID ファイルを保持する場所" @@ -1185,11 +1059,6 @@ msgstr "計測ドライバー" msgid "MinRtrAdvInterval setting for radvd.conf" msgstr " radvd.conf の MinRtrAdvInterval 設定" -msgid "Minimize polling by monitoring ovsdb for interface changes." -msgstr "" -"インターフェース変更の検出に関して ovsdb をモニターすることでポーリングが最小" -"化されます。" - #, python-format msgid "Missing key in mapping: '%s'" msgstr "マッピングにキーがありません: '%s'" @@ -1203,21 +1072,6 @@ msgstr "" "べてのブロードキャストトラフィックを送信できます。設定されないままにすると、" "マルチキャスト VXLAN モードを無効化します。" -msgid "" -"Multicast group(s) for vxlan interface. A range of group addresses may be " -"specified by using CIDR notation. Specifying a range allows different VNIs " -"to use different group addresses, reducing or eliminating spurious broadcast " -"traffic to the tunnel endpoints. To reserve a unique group for each possible " -"(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 表記を使用することで、一" -"定の範囲のグループアドレスを指定できます。範囲を指定するとさまざまな VNI がさ" -"まざまなグループアドレスを使用できるため、トンネルのエンドポイントへの不適切" -"なブロードキャストトラフィックを削減または排除できます。使用する可能性のある" -"各 (24 ビットの) VNI に独自のグループを予約するには、 /8 (239.0.0.0/8 など) " -"を使用します。この設定はすべてのエージェントで同じである必要があります。" - #, python-format msgid "Multiple default providers for service %s" msgstr "サービス %s のデフォルトのプロバイダーが複数あります" @@ -1240,12 +1094,6 @@ msgstr "フローの追加または変更について、1 つ以上のアクシã msgid "Name of Open vSwitch bridge to use" msgstr "使用する Open vSwitch ブリッジの名前" -msgid "" -"Name of nova region to use. Useful if keystone manages more than one region." -msgstr "" -"使用する nova リージョンの名前。Keystone で複数のリージョンを管理する場合に役" -"立ちます。" - msgid "Namespace of the router" msgstr "ルーターの名前空間" @@ -1323,16 +1171,6 @@ msgstr "" msgid "Not allowed to manually remove a router from an agent in 'dvr' mode." msgstr "'dvr' モードのエージェントからの手動でのルーター削除は許可されません。" -msgid "" -"Number of DHCP agents scheduled to host a tenant network. If this number is " -"greater than 1, the scheduler automatically assigns multiple DHCP agents for " -"a given tenant network, providing high availability for DHCP service." -msgstr "" -"テナントネットワークをホストするようにスケジュール設定された DHCP エージェン" -"トの数。この数が 1 より大きい場合、スケジューラーが自動的に特定のテナントネッ" -"トワークに複数の DHCP エージェントを割り当てるため、DHCP サービスの高可用性が" -"実現します。" - msgid "Number of backlog requests to configure the metadata server socket with" msgstr "メタデータサーバーソケットの構成に使用されるバックログ要求の数" @@ -1340,24 +1178,6 @@ msgid "Number of backlog requests to configure the socket with" msgstr "ソケットに設定するリクエストのバックログ数" msgid "" -"Number of bits in an ipv4 PTR zone that will be considered network prefix. " -"It has to align to byte boundary. Minimum value is 8. Maximum value is 24. " -"As a consequence, range of values is 8, 16 and 24" -msgstr "" -"ネットワークのプレフィックスとみなされる Ipv4 PTR ゾーン内のビット数。バイト" -"境界と同じ桁数である必要があります。最小値は 8 で、最大値は 24 です。そのた" -"め、使用できる値は 8、16、および 24 です。" - -msgid "" -"Number of bits in an ipv6 PTR zone that will be considered network prefix. " -"It has to align to nyble boundary. Minimum value is 4. Maximum value is 124. " -"As a consequence, range of values is 4, 8, 12, 16,..., 124" -msgstr "" -"ネットワークのプレフィックスとみなされる Ipv6 PTR ゾーン内のビット数。nyble " -"境界と同じ桁数である必要があります。最小値は 4 で、最大値は 124 です。そのた" -"め、使用できる値は 4、 8、12、16、... 124 です。" - -msgid "" "Number of floating IPs allowed per tenant. A negative value means unlimited." msgstr "" "テナント当たりに許可される Floating IP 数。負の値は無制限を意味します。 " @@ -1372,11 +1192,6 @@ msgstr "テナント当たりに許可されるポート数。負の値は無制 msgid "Number of routers allowed per tenant. A negative value means unlimited." msgstr "テナント当たりに許可されるルーター数。負の値は無制限を意味します。" -msgid "" -"Number of seconds between sending events to nova if there are any events to " -"send." -msgstr "送信するイベントがある場合の nova へのイベント送信間の秒数。" - msgid "Number of seconds to keep retrying to listen" msgstr "リッスンを試行し続ける秒数" @@ -1387,13 +1202,6 @@ msgstr "" "テナント当たりに許可されるセキュリティーグループ数。負の値は無制限を意味しま" "す。 " -msgid "" -"Number of security rules allowed per tenant. A negative value means " -"unlimited." -msgstr "" -"テナント当たりに許可されるセキュリティールール数。負の値は無制限を意味しま" -"す。 " - msgid "Number of subnets allowed per tenant, A negative value means unlimited." msgstr "テナント当たりに許可されるサブネット数。負の値は無制限を意味します。" @@ -1442,9 +1250,6 @@ msgid "Override the default dnsmasq settings with this file." msgstr "" "このファイルを使用して、デフォルトの dnsmasq 設定をオーバーライドします。" -msgid "Owner type of the device: network/compute" -msgstr "デバイスの所有者タイプ: network/compute" - msgid "POST requests are not supported on this resource." msgstr "POST 要求は、このリソースではサポートされていません。" @@ -1475,9 +1280,6 @@ msgid "Phase upgrade options do not accept revision specification" msgstr "" "フェーズのアップグレードオプションでは、変更の指定を行うことはできません" -msgid "Ping timeout" -msgstr "ping タイムアウト" - #, python-format msgid "Port %(id)s does not have fixed ip %(address)s" msgstr "ポート %(id)s に Fixed IP %(address)s がありません" @@ -1501,23 +1303,12 @@ msgstr "" msgid "Private key of client certificate." msgstr "クライアント証明書の秘密鍵。" -#, python-format -msgid "Probe %s deleted" -msgstr "プローブ %s が削除されました" - -#, python-format -msgid "Probe created : %s " -msgstr "作成されたプローブ: %s " - msgid "Process is already started" msgstr "プロセスが既に実行されています" msgid "Process is not running." msgstr "プロセスが実行されていません" -msgid "Protocol to access nova metadata, http or https" -msgstr "Nova メタデータ、http、または https にアクセスするためのプロトコル" - #, python-format msgid "Provider name %(name)s is limited by %(len)s characters" msgstr "プロバイダー名 %(name)s の制限は %(len)s 文字までです。" @@ -1568,27 +1359,6 @@ msgid "" "Repository does not contain HEAD files for contract and expand branches." msgstr "リポジトリーに縮小分岐と拡張分岐の HEAD ファイルが含まれていません。" -msgid "" -"Representing the resource type whose load is being reported by the agent. " -"This can be \"networks\", \"subnets\" or \"ports\". When specified (Default " -"is networks), the server will extract particular load sent as part of its " -"agent configuration object from the agent report state, which is the number " -"of resources being consumed, at every report_interval.dhcp_load_type can be " -"used in combination with network_scheduler_driver = neutron.scheduler." -"dhcp_agent_scheduler.WeightScheduler When the network_scheduler_driver is " -"WeightScheduler, dhcp_load_type can be configured to represent the choice " -"for the resource being balanced. Example: dhcp_load_type=networks" -msgstr "" -"負荷がエージェントによって報告されているリソースタイプを表します。このタイプ" -"には、\"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 "要求が失敗しました。要求の処理中に内部サーバーエラーが発生しました。" @@ -1666,14 +1436,6 @@ msgstr "" "ノード状態をサーバーに報告する間隔 (秒)。agent_down_time 未満である必要があ" "ります。agent_down_time の半分以下であれば最適です。" -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 の 2 倍に" -"してください。" - #, python-format msgid "Security Group %(id)s %(reason)s." msgstr "セキュリティーグループ %(id)s %(reason)s。" @@ -1712,16 +1474,6 @@ msgstr "" "セキュリティーグループルールのプロトコル %(protocol)s が対応していません。使" "用できるのは、プロトコルの値 %(values)s と整数値 [0 から 255 まで] のみです。" -msgid "" -"Send notification to nova when port data (fixed_ips/floatingip) changes so " -"nova can update its cache." -msgstr "" -"nova がそのキャッシュを更新できるように、ポートデータ (fixed_ips/floatingip) " -"が変更されたときに通知を nova に送信します。" - -msgid "Send notification to nova when port status changes" -msgstr "ポート状態の変更時の nova への通知送信" - #, python-format msgid "" "Service provider '%(provider)s' could not be found for service type " @@ -1739,20 +1491,6 @@ msgstr "" "サービスタイプ %(service_type)s にはデフォルトのサービスプロバイダーがありま" "せん" -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 "" -"エージェントによる SIGTERM 受信後の新規 rpc 呼び出しの新規タイムアウト(秒) を" -"設定します。値を 0 に設定すると、rpc タイムアウトは変更されません" - -msgid "" -"Set or un-set the don't fragment (DF) bit on outgoing IP packet carrying GRE/" -"VXLAN tunnel." -msgstr "" -"GRE/VXLAN トンネルを構成した発信 IP パケットで、フラグメント禁止 (DF) ビット" -"を設定または設定解除します。" - msgid "Shared address scope can't be unshared" msgstr "共有アドレススコープは共有を解除できません" @@ -1769,9 +1507,6 @@ msgstr "ルーターインターフェースのサブネットにはゲートウ msgid "Subnet pool has existing allocations" msgstr "サブネットプールに既存の割り当てがあります" -msgid "Subnet used for the l3 HA admin network." -msgstr "l3 HA 管理ネットワークに使用されるサブネット。" - msgid "" "System-wide flag to determine the type of router that tenants can create. " "Only admin can override." @@ -1785,9 +1520,6 @@ msgstr "Neutron メタデータ名前空間プロキシーが使用する TCP Po msgid "TCP Port used by Nova metadata server." msgstr "Nova メタデータサーバーによって使用される TCP ポート。" -msgid "TTL for vxlan interface protocol packets." -msgstr "vxlan インターフェースプロトコルパケットの TTL。" - #, python-format msgid "Tag %(tag)s could not be found." msgstr "タグ %(tag)s が見つかりませんでした。" @@ -1804,21 +1536,6 @@ msgstr "管理者のコンテキストにおける designate への接続用テã msgid "Tenant name for connecting to designate in admin context" msgstr "管理者のコンテキストにおける designate への接続用テナント名" -msgid "" -"The DHCP server can assist with providing metadata support on isolated " -"networks. Setting this value to True will cause the DHCP server to append " -"specific host routes to the DHCP request. The metadata service will only be " -"activated when the subnet does not contain any router port. The guest " -"instance must be configured to request host routes via DHCP (Option 121). " -"This option doesn't have any effect when force_metadata is set to True." -msgstr "" -"DHCP サーバーは孤立したネットワークに対してメタデータサポートを提供することが" -"できます。この値を True に設定すると、DHCP サーバーは DHCP 要求に対する特定の" -"ホストへの経路を追加できます。このメタデータサービスが有効化されるのは、サブ" -"ネットにルーターのポートが含まれない場合に限られます。ゲストインスタンスに" -"は、DHCP (オプション 121) 経由でホストの経路を要求するよう設定を行う必要があ" -"ります。force_metadata を True に設定する場合、このオプションは機能しません。" - msgid "The UDP port to use for VXLAN tunnels." msgstr "VXLAN トンネルで使用する UDP ポート。" @@ -1839,31 +1556,12 @@ msgstr "" "しません。4 つ目のオクテットが 00 の場合、これも使用できます。その他のオク" "テットはランダムに生成されます。" -msgid "" -"The base mac address used for unique DVR instances by Neutron. The first 3 " -"octets will remain unchanged. If the 4th octet is not 00, it will also be " -"used. The others will be randomly generated. The 'dvr_base_mac' *must* be " -"different from 'base_mac' to avoid mixing them up with MAC's allocated for " -"tenant ports. A 4 octet example would be dvr_base_mac = fa:16:3f:4f:00:00. " -"The default is 3 octet" -msgstr "" -"Neutron によって独自の DVR インスタンスに使用される基本の MAC アドレス。最初" -"の 3 つのオクテットは変更されません。4 つ目のオクテットが 00 でない場合は、" -"このオクテットも使用できます。その他のオクテットはランダムに生成されます。 テ" -"ナントポートに割り当てられた MAC アドレスとの混同を避けるために、 " -"'dvr_base_mac' は 'base_mac' とは違う値である必要があります。4 つ目のオクテッ" -"トの例としては、dvr_base_mac = fa:16:3f:4f:00:00 があります。デフォルトは、3 " -"つ目のオクテットです。" - msgid "The core plugin Neutron will use" msgstr "Neutron が使用するコアプラグイン" msgid "The driver used to manage the DHCP server." msgstr "DHCP サーバーの管理に使用されるドライバー。" -msgid "The driver used to manage the virtual interface." -msgstr "仮想インターフェースの管理に使用されるドライバー。" - msgid "" "The email address to be used when creating PTR zones. If not specified, the " "email address will be admin@<dns_domain>" @@ -1872,54 +1570,14 @@ msgstr "" "スは admin@<dns_domain> になります。" msgid "" -"The maximum number of items returned in a single response, value was " -"'infinite' or negative integer means no limit" -msgstr "" -"1 回の応答で最大数の項目が返されました。値は 'infinite' または (無制限を意味" -"する) 負の整数でした" - -msgid "" -"The network type to use when creating the HA network for an HA router. By " -"default or if empty, the first 'tenant_network_types' is used. This is " -"helpful when the VRRP traffic should use a specific network which is not the " -"default one." -msgstr "" -"HA ルーター用に HA ネットワークを作成する際に使用するネットワークタイプ。デ" -"フォルトまたはこの値が空の場合、最初の 'tenant_network_types' が使用されま" -"す。VRRP トラフィックがデフォルトではない特定のネットワークを使用しなければな" -"らない場合には、この設定が役立ちます。" - -msgid "" "The number of seconds the agent will wait between polling for local device " "changes." msgstr "" "ローカルデバイスの変更のポーリング間にエージェントが待機する間隔 (秒)。" -msgid "" -"The number of seconds to wait before respawning the ovsdb monitor after " -"losing communication with it." -msgstr "" -"ovsdb モニターとの通信が途絶えた後で ovsdb モニターを再作成する前に待機する時" -"間 (秒)" - msgid "The number of sort_keys and sort_dirs must be same" msgstr "sort_keys と sort_dirs の数は同じでなければなりません" -msgid "" -"The path for API extensions. Note that this can be a colon-separated list of " -"paths. For example: api_extensions_path = extensions:/path/to/more/exts:/" -"even/more/exts. The __path__ of neutron.extensions is appended to this, so " -"if your extensions are in there you don't need to specify them here." -msgstr "" -"API 強化機能のパス。このパスはコロンで区切られたパスのリストであることに注意" -"してください。例としては、api_extensions_path = extensions:/path/to/more/" -"exts:/even/more/exts があります。このパスには neutron.extensions の __path__ " -"が付いているため、強化機能がこのパスにある場合、ここで指定する必要はありませ" -"ん。" - -msgid "The physical network name with which the HA network can be created." -msgstr "HA ネットワークを作成可能な物理ネットワーク名。" - #, python-format msgid "The port '%s' was deleted" msgstr "ポート '%s' が削除されました" @@ -1977,14 +1635,6 @@ msgstr "トンネル IP 値が ML2 プラグインに必要です" msgid "Tunnel bridge to use." msgstr "使用するトンネルブリッジ。" -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 のカタ" -"ログで参照され、public、internal、または admin のいずれかである必要がありま" -"す。" - msgid "URL for connecting to designate" msgstr "designate への接続用 URL" @@ -2104,14 +1754,6 @@ msgid "Use either --delta or relative revision, not both" msgstr "--delta と相対的な変更の両方ではなく、どちらか一方を使用してください" 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 " -"をインストールする必要があります。" - -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." @@ -2156,59 +1798,15 @@ msgstr "" "(ミリ秒)。詳細情報については、tc-tbf マニュアルを参照してください。" msgid "" -"When proxying metadata requests, Neutron signs the Instance-ID header with a " -"shared secret to prevent spoofing. You may select any string for a secret, " -"but it must match here and in the configuration used by the Nova Metadata " -"Server. NOTE: Nova uses the same config key, but in [neutron] section." -msgstr "" -"メタデータ要求のプロキシーを実行する際に、Neutron はスプーフィングを防止する" -"ために共有秘密鍵を使用して インスタンス ID ヘッダーに署名します。秘密鍵として" -"任意の文字列を選択できるものの、その値はここと Nova Metadata Server が使用す" -"る設定で一致する必要があります。注意: Nova は同じ設定鍵を使用するものの、その" -"値は [neutron] セクションにあります。" - -msgid "" "Where to store Neutron state files. This directory must be writable by the " "agent." msgstr "" "Neutron 状態ファイルの保管場所。このディレクトリーは、エージェントが書き込み" "を行える場所でなければなりません。" -msgid "" -"With IPv6, the network used for the external gateway does not need to have " -"an associated subnet, since the automatically assigned link-local address " -"(LLA) can be used. However, an IPv6 gateway address is needed for use as the " -"next-hop for the default route. If no IPv6 gateway address is configured " -"here, (and only then) the neutron router will be configured to get its " -"default route from router advertisements (RAs) from the upstream router; in " -"which case the upstream router must also be configured to send these RAs. " -"The ipv6_gateway, when configured, should be the LLA of the interface on the " -"upstream router. If a next-hop using a global unique address (GUA) is " -"desired, it needs to be done via a subnet allocated to the network and not " -"through this parameter. " -msgstr "" -"IPv6 では、自動的に割り当てられたリンクローカルアドレス (LLA) を使用できるた" -"め、外部ゲートウェイに使用するネットワークにはサブネットを関連付ける必要はあ" -"りません。ただし、IPv6 ゲートウェイアドレスはデフォルト経路のネクストホップと" -"して使用するために必要です。IPv6 ゲートウェイアドレスをここで構成しない場合に" -"のみ、上流ルーターのルーター広告 (RA) からデフォルト経路を取得するように " -"Neutron ルーターが構成されます。この場合、これらの RA を送信するように上流" -"ルーターを構成することも必要です。ipv6_gateway を構成する場合、これは上流ルー" -"ター上のインターフェースの LLA でなければなりません。グローバルユニークアドレ" -"ス (GUA) を使用したネクストホップが必要な場合は、このパラメーターを使用するの" -"ではなく、ネットワークに割り振られたサブネットを介してこれを行う必要がありま" -"す。" - msgid "You must implement __call__" 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] のいずれかを指定する必要があります" - msgid "You must provide a revision or relative delta" msgstr "変更または相対デルタを指定する必要があります" diff --git a/neutron/locale/ko_KR/LC_MESSAGES/neutron.po b/neutron/locale/ko_KR/LC_MESSAGES/neutron.po index d185499328..32e9bfe043 100644 --- a/neutron/locale/ko_KR/LC_MESSAGES/neutron.po +++ b/neutron/locale/ko_KR/LC_MESSAGES/neutron.po @@ -15,7 +15,7 @@ msgid "" msgstr "" "Project-Id-Version: neutron VERSION\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2023-01-26 15:02+0000\n" +"POT-Creation-Date: 2023-05-15 17:54+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -141,25 +141,10 @@ msgstr "코어 자원에 테스트 속성을 추가합니다." msgid "Agent %(id)s is not a L3 Agent or has been disabled" msgstr "%(id)s 에이전트가 L3 에이전트가 아니거나 사용 안함 상태임" -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 agent " -"until admin changes admin_state_up to True." -msgstr "" -"enable_new_agents=False인 경우 에이전트는 admin_state_up=False로 시작합니다. " -"이 경우 사용자의 자원은 관리자가 admin_state_up을 True로 변경할 때까지 에이전" -"트에 대해 자동으로 스케줄되지 않습니다. " - #, python-format msgid "Agent updated: %(payload)s" msgstr "업데이트된 에이전트: %(payload)s" -msgid "Allow auto scheduling networks to DHCP agent." -msgstr "DHCP 에이전트에 대한 네트워크 자동 스케줄링을 허용합니다. " - -msgid "Allow auto scheduling of routers to L3 agent." -msgstr "L3 에이전트에 대한 라우터 자동 스케줄링을 허용합니다." - msgid "Allow running metadata proxy." msgstr "메타데이터 프록시 실행을 허용합니다." @@ -172,9 +157,6 @@ msgstr "PTR 레코드의 작성 허용" msgid "Allow the usage of the bulk API" msgstr "벌크 API 사용 허용" -msgid "Allow to perform insecure SSL (https) requests to nova metadata" -msgstr "nova 메타데이터에 대한 비보안 SSL(https) 요청 수행 허용" - msgid "" "Allows for serving metadata requests coming from a dedicated metadata access " "network whose CIDR is 169.254.169.254/16 (or larger prefix), and is " @@ -371,9 +353,6 @@ msgstr "" msgid "Cleanup resources of a specific agent type only." msgstr "특정 에이전트 유형의 자원만 정리합니다." -msgid "Client certificate for nova metadata api server." -msgstr "nova 메타데이터 api 서버에 대한 클라이언트 인증서입니다." - msgid "" "Comma-separated list of <network_device>:<vfs_to_exclude> tuples, mapping " "network_device to the agent's node-specific list of virtual functions that " @@ -431,24 +410,10 @@ msgid "" "Comma-separated list of the DNS servers which will be used as forwarders." msgstr "쉼표로 분리된 DNS 서버의 목록이며 전달자로 사용됩니다." -msgid "Command to execute" -msgstr "실행할 명령" - -msgid "Config file for interface driver (You may also use l3_agent.ini)" -msgstr "인터페이스 드라이버에 대한 구성 파일(l3_agent.ini도 사용할 수 있음)" - #, python-format msgid "Conflicting value ethertype %(ethertype)s for CIDR %(cidr)s" msgstr "CIDR %(cidr)s에 대한 충돌하는 값 ethertype %(ethertype)s" -msgid "" -"Controls whether the neutron security group API is enabled in the server. It " -"should be false when using no security groups or using the nova security " -"group API." -msgstr "" -"서버에서 neutron 보안 그룹 API가 사용되는지 여부를 제어합니다.보안 그룹을 사" -"용하지 않거나 nova 보안 그룹 API를 사용할 때는 false이어야 합니다." - #, python-format msgid "Could not bind to %(host)s:%(port)s after trying for %(time)d seconds" msgstr "%(time)d후 시도한 다음 %(host)s:%(port)s에 바인딩할 수 없습니다" @@ -499,11 +464,6 @@ msgid "" msgstr "" "테넌트당 허용되는 기본 RBAC 항목 수입니다. 음수 값은 무제한을 의미합니다. " -msgid "" -"Default number of resource allowed per tenant. A negative value means " -"unlimited." -msgstr "테넌트당 허용되는 기본 자원 수입니다. 음수 값은 무제한을 의미합니다." - msgid "Default security group" msgstr "기본 보안 그룹" @@ -574,21 +534,6 @@ msgstr "외부 DNS 통합을 위한 드라이버." msgid "Driver for security groups firewall in the L2 agent" msgstr "L2 에이전트의 보안 그룹 방화벽에 대한 드라이버" -msgid "Driver to use for scheduling network to DHCP agent" -msgstr "DHCP 에이전트에 대한 네트워크 스케줄링에 사용할 드라이버" - -msgid "Driver to use for scheduling router to a default L3 agent" -msgstr "기본 L3 에이전트에 대한 라우터 스케줄링에 사용할 드라이버" - -msgid "" -"Driver used for ipv6 prefix delegation. This needs to be an entry point " -"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 네임스페이스에서 정의된 시작점이어야 합니다. neutron 소스와 함께 " -"포함된 시작점은 setup.cfg를 참조하십시오. " - #, python-format msgid "" "Duplicate L3HARouterAgentPortBinding is created for router(s) %(router)s. " @@ -633,13 +578,6 @@ msgid "Enable SSL on the API server" msgstr "API 서버에서 SSL 연결 활성화" msgid "" -"Enable VXLAN on the agent. Can be enabled when agent is managed by ml2 " -"plugin using linuxbridge mechanism driver" -msgstr "" -"에이전트에서 VXLAN을 사용 가능하게 설정하십시오. linuxbridge 메커니즘 드라이" -"버를 사용하여 ml2 플러그인이 에이전트를 관리할 경우 사용할 수 있습니다." - -msgid "" "Enable services on an agent with admin_state_up False. If this option is " "False, when admin_state_up of an agent is turned False, services on it will " "be disabled. Agents with admin_state_up False are not selected for automatic " @@ -692,13 +630,6 @@ msgstr "" "서비스 플러그인 %(service_plugin)s에 필요한 확장 드라이버 %(driver)s을(를) 찾" "을 수 없음" -msgid "" -"Extension to use alongside ml2 plugin's l2population mechanism driver. It " -"enables the plugin to populate VXLAN forwarding table." -msgstr "" -"ml2 플러그인의 l2population 메커니즘 드라이버와 함께 사용할 확장기능. 이를 통" -"해플러그인이 VXLAN 전달 테이블을 채울 수 있습니다." - #, python-format msgid "Extension with alias %s does not exist" msgstr "별명이 %s인 확장이 존재하지 않음" @@ -798,18 +729,6 @@ msgstr "" "ICMP 코드 (port-range-max) %(value)s이(가) 제공되지만 ICMP 유형(port-range-" "min)이 누락되었습니다." -msgid "ID of network" -msgstr "네트워크의 ID" - -msgid "ID of network to probe" -msgstr "프로브할 네트워크의 ID" - -msgid "ID of probe port to delete" -msgstr "삭제할 프로브 포트의 ID" - -msgid "ID of probe port to execute command" -msgstr "명령을 실행할 프로브 포트의 ID" - msgid "ID of the router" msgstr "라우터의 ID" @@ -871,18 +790,6 @@ msgid "Illegal IP version number" msgstr "올바르지 않은 IP 버전 번호" msgid "" -"In some cases the Neutron router is not present to provide the metadata IP " -"but the DHCP server can be used to provide this info. Setting this value " -"will force the DHCP server to append specific host routes to the DHCP " -"request. If this option is set, then the metadata service will be activated " -"for all the networks." -msgstr "" -"경우에 따라 메타데이터 IP를 제공하는 Neutron 라우터는 없지만 DHCP 서버를 사용" -"하여 이 정보를 제공할 수 있습니다. 이 값을 설정하면 DHCP 서버가 특정 호스트 " -"경로를 DHCP 요청에 강제로 추가합니다. 이 옵션이 설정되면 모든 네트워크의 메타" -"데이터 서비스가 활성화됩니다." - -msgid "" "Indicates that this L3 agent should also handle routers that do not have an " "external network gateway configured. This option should be True only for a " "single agent in a Neutron deployment, and may be False for all agents if all " @@ -920,11 +827,6 @@ msgstr "" msgid "Interface to monitor" msgstr "모니터할 인터페이스" -msgid "" -"Interval between checks of child process liveness (seconds), use 0 to disable" -msgstr "" -"하위 프로세스 활동 확인 간격(초), 사용 안함으로 설정하려면 0을 지정하십시오." - msgid "Interval between two metering measures" msgstr "2개의 측정 조치 간의 간격" @@ -1001,13 +903,6 @@ msgid "Invalid value for port %(port)s" msgstr "%(port)s 포트에 대한 올바르지 않은 값" msgid "" -"Iptables mangle mark used to mark ingress from external network. This mark " -"will be masked with 0xffff so that only the lower 16 bits will be used." -msgstr "" -"외부 네트워크의 입구를 표시하는 데 사용되는 Iptables mangle 표시입니다. 이 표" -"시는 하위 16비트만 사용되도록 0xffff로 마스크됩니다. " - -msgid "" "Iptables mangle mark used to mark metadata valid requests. This mark will be " "masked with 0xffff so that only the lower 16 bits will be used." msgstr "" @@ -1063,12 +958,6 @@ msgstr "메타데이터 프록시 UNIX 도메인 소켓의 위치" msgid "Location to store DHCP server config files." msgstr "DHCP 서버 구성 파일을 저장할 위치." -msgid "Location to store IPv6 PD files." -msgstr "IPv6 PD 파일을 저장할 위치입니다. " - -msgid "Location to store IPv6 RA config files" -msgstr "IPv6 RA 구성 파일을 저장할 위치" - msgid "Location to store child pid files" msgstr "하위 pid 파일을 저장할 위치" @@ -1140,9 +1029,6 @@ msgstr "측정 드라이버" msgid "MinRtrAdvInterval setting for radvd.conf" msgstr "radvd.conf의 MinRtrAdvInterval 설정" -msgid "Minimize polling by monitoring ovsdb for interface changes." -msgstr "인터페이스 변경사항에 대한 ovsdb를 모니터링하여 폴링을 최소화합니다." - #, python-format msgid "Missing key in mapping: '%s'" msgstr "맵핑에서 키 누락: '%s'" @@ -1156,20 +1042,6 @@ msgstr "" "이 멀티캐스트 그룹에 보낼 수 있습니다. 구성되지 않은 상태로 두면 멀티캐스트 " "VXLAN 모드가 사용되지 않습니다." -msgid "" -"Multicast group(s) for vxlan interface. A range of group addresses may be " -"specified by using CIDR notation. Specifying a range allows different VNIs " -"to use different group addresses, reducing or eliminating spurious broadcast " -"traffic to the tunnel endpoints. To reserve a unique group for each possible " -"(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 표기법을 사" -"용하여 지정할 수 있습니다. 범위를 지정하면 여러 다른 VNI에서 여러 다른 그룹 " -"주소를 사용할 수 있으므로, 터널 엔드포인트에 대한 의사 브로드캐스트 트래픽이 " -"감소하거나 제거됩니다. 가능한 각 (24비트) VNI의 고유 그룹을 유지하려면 /8을 " -"사용하십시오(예: 239.0.0.0/8). 이 설정은 모든 에이전트에서 같아야 합니다." - #, python-format msgid "Multiple default providers for service %s" msgstr "%s 서비스에 대한 다중 기본 제공자 " @@ -1190,12 +1062,6 @@ msgstr "플로우 추가 또는 수정 시 하나 이상의 조치를 지정해ì msgid "Name of Open vSwitch bridge to use" msgstr "사용할 열린 vSwitch 브릿지의 이름" -msgid "" -"Name of nova region to use. Useful if keystone manages more than one region." -msgstr "" -"사용할 nova 리젼의 이름입니다. 키스톤이 둘 이상의 리젼을 관리할 경우 유용합니" -"다." - msgid "Namespace of the router" msgstr "라우터의 네임스페이스" @@ -1273,15 +1139,6 @@ msgstr "'dvr' 모드에서 수동으로 에이전트에 라우터를 지정할 ì msgid "Not allowed to manually remove a router from an agent in 'dvr' mode." msgstr "'dvr' 모드에서 수동으로 에이전트에서 라우터를 제거할 수 없습니다." -msgid "" -"Number of DHCP agents scheduled to host a tenant network. If this number is " -"greater than 1, the scheduler automatically assigns multiple DHCP agents for " -"a given tenant network, providing high availability for DHCP service." -msgstr "" -"테넌트 네트워크를 호스팅하기 위해 스케줄된 DHCP 에이전트의 수입니다. 이 숫자" -"가 1보다 크면 스케줄러는 지정된 테넌트 네트워크에 대해 다중 DHCP 에이전트를 " -"자동으로 지정하여 DHCP 서비스에 대한 고가용성을 제공합니다. " - msgid "Number of backlog requests to configure the metadata server socket with" msgstr "메타데이터 서버 소켓을 구성하기 위한 백로그 요청 수" @@ -1289,24 +1146,6 @@ msgid "Number of backlog requests to configure the socket with" msgstr "소켓을 설정하려는 백로그 요청 횟수" msgid "" -"Number of bits in an ipv4 PTR zone that will be considered network prefix. " -"It has to align to byte boundary. Minimum value is 8. Maximum value is 24. " -"As a consequence, range of values is 8, 16 and 24" -msgstr "" -"네트워크 접두어로 고려될 ipv4 PTR 구역의 비트 수입니다. 바이트 경계에 맞게 정" -"렬해야 합니다. 최소값은 8이고 최대값은 24입니다. 결과적으로 값의 범위는 8, " -"16 및 24입니다." - -msgid "" -"Number of bits in an ipv6 PTR zone that will be considered network prefix. " -"It has to align to nyble boundary. Minimum value is 4. Maximum value is 124. " -"As a consequence, range of values is 4, 8, 12, 16,..., 124" -msgstr "" -"네트워크 접두어로 고려될 ipv6 PTR 구역의 비트 수입니다. nyble 경계에 맞게 정" -"렬해야 합니다. 최소값은 4이고 최대값은 124입니다. 결과적으로 값의 범위는 4, " -"8, 12, 16,..., 124입니다." - -msgid "" "Number of floating IPs allowed per tenant. A negative value means unlimited." msgstr "테넌트당 허용된 부동 IP 수입니다. 음수 값은 무제한을 의미합니다." @@ -1320,11 +1159,6 @@ msgstr "테넌트당 허용되는 포트 수입니다. 음수 값은 무제한ì� msgid "Number of routers allowed per tenant. A negative value means unlimited." msgstr "테넌트당 허용된 라우터 수입니다. 음수 값은 무제한을 의미합니다." -msgid "" -"Number of seconds between sending events to nova if there are any events to " -"send." -msgstr "보낼 이벤트가 있는 경우 nova에 전송하는 이벤트 간의 시간(초)입니다." - msgid "Number of seconds to keep retrying to listen" msgstr "감청 재시도 계속할 시간" @@ -1333,11 +1167,6 @@ msgid "" "unlimited." msgstr "테넌트당 허용된 보안 그룹 수입니다. 음수 값은 무제한을 의미합니다." -msgid "" -"Number of security rules allowed per tenant. A negative value means " -"unlimited." -msgstr "테넌트당 허용된 보안 규칙 수입니다. 음수 값은 무제한을 의미합니다." - msgid "Number of subnets allowed per tenant, A negative value means unlimited." msgstr "테넌트당 허용되는 서브넷 수입니다. 음수 값은 무제한을 의미합니다." @@ -1381,9 +1210,6 @@ msgstr "" msgid "Override the default dnsmasq settings with this file." msgstr "기본 dnsmasq 설정을 이 파일로 대체합니다." -msgid "Owner type of the device: network/compute" -msgstr "디바이스의 소유자 유형: network/compute" - msgid "POST requests are not supported on this resource." msgstr "이 자원에서 POST 요청이 지원되지 않습니다." @@ -1413,9 +1239,6 @@ msgstr "통합 브릿지에 대한 터널 브릿지에 있는 피어 패치 포í msgid "Phase upgrade options do not accept revision specification" msgstr "단계 업그레이드 옵션이 개정 스펙을 승인하지 않음" -msgid "Ping timeout" -msgstr "Ping 제한시간 초과" - #, python-format msgid "Port %(id)s does not have fixed ip %(address)s" msgstr "%(id)s 포트가 고정 IP %(address)s을(를) 갖지 않음" @@ -1438,23 +1261,12 @@ msgstr "접두부 위임은 IPv6 서브넷에만 사용할 수 있습니다. " msgid "Private key of client certificate." msgstr "클라이언트 인증서의 개인 키입니다." -#, python-format -msgid "Probe %s deleted" -msgstr "%s 프로브가 삭제되었음" - -#, python-format -msgid "Probe created : %s " -msgstr "프로브 작성: %s " - msgid "Process is already started" msgstr "프로세스가 이미 시작됨" msgid "Process is not running." msgstr "프로세스가 실행 중이지 않습니다." -msgid "Protocol to access nova metadata, http or https" -msgstr "nova 메타데이터에 액세스하기 위한 프로토콜, http 또는 https" - #, python-format msgid "Provider name %(name)s is limited by %(len)s characters" msgstr "제공자 이름 %(name)s은(는) %(len)s자로 제한됨" @@ -1504,26 +1316,6 @@ msgid "" "Repository does not contain HEAD files for contract and expand branches." msgstr "저장소에 계약 및 확장 분기의 HEAD 파일이 포함되지 않습니다." -msgid "" -"Representing the resource type whose load is being reported by the agent. " -"This can be \"networks\", \"subnets\" or \"ports\". When specified (Default " -"is networks), the server will extract particular load sent as part of its " -"agent configuration object from the agent report state, which is the number " -"of resources being consumed, at every report_interval.dhcp_load_type can be " -"used in combination with network_scheduler_driver = neutron.scheduler." -"dhcp_agent_scheduler.WeightScheduler When the network_scheduler_driver is " -"WeightScheduler, dhcp_load_type can be configured to represent the choice " -"for the resource being balanced. Example: dhcp_load_type=networks" -msgstr "" -"에이전트에서 로드를 보고하는 자원 유형을 나타냅니다. 이는 \"네트워크\", \"서" -"브넷\" 또는 \"포트\"입니다. 이를 지정하는 경우 (기본값은 네트워크임) 서버는 " -"network_scheduler_driver = neutron.scheduler.dhcp_agent_scheduler." -"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." msgstr "요청 실패: 요청을 처리하는 중에 내부 서버 오류가 발생했습니다. " @@ -1600,13 +1392,6 @@ msgstr "" "서버에 대한 상태를 보고하는 노드 사이의 시간(초)이며 agent_down_time보다 짧아" "야 하며 절반이거나 agent_down_time보다 짧은 경우 최적입니다." -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의 두 배 이상이어야 합니다." - #, python-format msgid "Security Group %(id)s %(reason)s." msgstr "보안 그룹 %(id)s %(reason)s입니다. " @@ -1643,16 +1428,6 @@ msgstr "" "보안 그룹 규칙 프로토콜 %(protocol)s이(가) 지원되지 않습니다. 프로토콜 값 " "%(values)s 및 정수 표시 [0 - 255]만 지원됩니다. " -msgid "" -"Send notification to nova when port data (fixed_ips/floatingip) changes so " -"nova can update its cache." -msgstr "" -"포트 데이터(fixed_ips/floatingip)가 변경되면 알림을 nova에 보냅니다. 이에 따" -"라 nova는 해당 캐시를 업데이트할 수 있습니다." - -msgid "Send notification to nova when port status changes" -msgstr "포트 상태가 변경되면 알림을 nova에 보냅니다." - #, python-format msgid "" "Service provider '%(provider)s' could not be found for service type " @@ -1668,20 +1443,6 @@ msgstr "DHCPv6 접두부 위임을 처리할 서비스입니다. " msgid "Service type %(service_type)s does not have a default service provider" msgstr "%(service_type)s 서비스 유형에 기본 서비스 제공자가 없음" -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 "" -"에이전트에서 SIGTERM을 수신한 후에 새 rpc 호출에 대한 새 제한시간(초)을 설정" -"합니다. 값을 0으로 설정하면 rpc 제한시간이 변경되지 않습니다." - -msgid "" -"Set or un-set the don't fragment (DF) bit on outgoing IP packet carrying GRE/" -"VXLAN tunnel." -msgstr "" -"GRE/VXLAN 터널을 전송하는 발신 IP 패킷에 DF(Don't Fragment) 비트를 설정하거" -"나 설정 해제하십시오." - msgid "Shared address scope can't be unshared" msgstr "공유 주소 범위는 공유 해제할 수 없음" @@ -1698,9 +1459,6 @@ msgstr "라우터 인터페이스에 대한 서브넷은 게이트웨이 IP를 ê msgid "Subnet pool has existing allocations" msgstr "서브넷 풀에 기존 할당이 있음" -msgid "Subnet used for the l3 HA admin network." -msgstr "l3 HA 관리 네트워크에 사용된 서브넷입니다." - msgid "" "System-wide flag to determine the type of router that tenants can create. " "Only admin can override." @@ -1714,9 +1472,6 @@ msgstr "Neutron 메타데이터 네임스페이스 프록시가 사용하는 TCP msgid "TCP Port used by Nova metadata server." msgstr "Nova 메타데이터 서버가 사용한 TCP 포트입니다. " -msgid "TTL for vxlan interface protocol packets." -msgstr "vxlan 인터페이스 프로토콜 패킷용 TTL." - #, python-format msgid "Tag %(tag)s could not be found." msgstr "%(tag)s 태그를 찾을 수 없습니다." @@ -1733,21 +1488,6 @@ msgstr "관리 컨텍스트에서 지정하기 위해 연결할 테넌트 ID" msgid "Tenant name for connecting to designate in admin context" msgstr "관리 컨텍스트에서 지정하기 위해 연결할 테넌트 이름" -msgid "" -"The DHCP server can assist with providing metadata support on isolated " -"networks. Setting this value to True will cause the DHCP server to append " -"specific host routes to the DHCP request. The metadata service will only be " -"activated when the subnet does not contain any router port. The guest " -"instance must be configured to request host routes via DHCP (Option 121). " -"This option doesn't have any effect when force_metadata is set to True." -msgstr "" -"DHCP 서버는 격리된 네트워크에서 메타데이터 지원을 제공하도록 지원할 수 있습니" -"다. 이 값을 True로 설정하면 DHCP 서버가 특정 호스트 경로를 DHCP 요청에 추가합" -"니다. 메타데이터 서비스는 서브넷에 라우터 포트가 포함되지 않은 경우에만 활성" -"화됩니다. DHCP를 통해 호스트 경로를 요청하려면 게스트 인스턴스가 구성되어야 " -"합니다(옵션 121). 이 옵션은 force_metadata가 True로 설정된 경우 적용되지 않습" -"니다." - msgid "The UDP port to use for VXLAN tunnels." msgstr "VXLAN 터널에 사용하는 UDP 포트" @@ -1768,29 +1508,12 @@ msgstr "" "태로 남습니다. 네 번째 옥텟이 00이 아니면 이 옥텟도 사용됩니다. 다른 옥텟은 " "임의로 생성됩니다." -msgid "" -"The base mac address used for unique DVR instances by Neutron. The first 3 " -"octets will remain unchanged. If the 4th octet is not 00, it will also be " -"used. The others will be randomly generated. The 'dvr_base_mac' *must* be " -"different from 'base_mac' to avoid mixing them up with MAC's allocated for " -"tenant ports. A 4 octet example would be dvr_base_mac = fa:16:3f:4f:00:00. " -"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 옥텟입니다. " - msgid "The core plugin Neutron will use" msgstr "Neutron이 사용할 코어 플러그인" msgid "The driver used to manage the DHCP server." msgstr "DHCP 서버를 관리하는 데 사용되는 드라이버입니다. " -msgid "The driver used to manage the virtual interface." -msgstr "가상 인터페이스를 관리하는 데 사용되는 드라이버입니다. " - msgid "" "The email address to be used when creating PTR zones. If not specified, the " "email address will be admin@<dns_domain>" @@ -1799,50 +1522,13 @@ msgstr "" "는 admin@<dns_domain>입니다." msgid "" -"The maximum number of items returned in a single response, value was " -"'infinite' or negative integer means no limit" -msgstr "" -"단일 응답으로 최대 항목 수가 리턴되었습니다. 값이 'infinite' 또는 음수인 경" -"우 제한이 없다는 의미입니다. " - -msgid "" -"The network type to use when creating the HA network for an HA router. By " -"default or if empty, the first 'tenant_network_types' is used. This is " -"helpful when the VRRP traffic should use a specific network which is not the " -"default one." -msgstr "" -"HA 라우터에 대한 HA 네트워크 작성 시 사용할 네트워크 유형입니다. 기본적으로 " -"또는 비어 있는 경우 첫 번째 'tenant_network_types'가 사용됩니다. 이는 VRRP 트" -"래픽이 기본값이 아닌 특정 네트워크를 사용해야 하는 경우에 유용합니다. " - -msgid "" "The number of seconds the agent will wait between polling for local device " "changes." msgstr "에이전트가 로컬 디바이스 변경을 폴링하는 사이에 대기하는 시간(초). " -msgid "" -"The number of seconds to wait before respawning the ovsdb monitor after " -"losing communication with it." -msgstr "" -"통신이 유실된 후에 ovsdb 모니터를 재파생하기 전에 대기할 시간(초)입니다." - msgid "The number of sort_keys and sort_dirs must be same" msgstr "sort_keys 및 sort_dirs의 수가 같아야 함" -msgid "" -"The path for API extensions. Note that this can be a colon-separated list of " -"paths. For example: api_extensions_path = extensions:/path/to/more/exts:/" -"even/more/exts. The __path__ of neutron.extensions is appended to this, so " -"if your extensions are in there you don't need to specify them here." -msgstr "" -"API 확장의 경로입니다. 이 경로는 콜론으로 구분된 경로 목록일 수 있습니다. " -"예: api_extensions_path = extensions:/path/to/more/exts:/even/more/exts. " -"neutron.extensions의 __path__가 이 경로에 추가되므로, 해당 위치에 확장이 있으" -"면 여기에 지정하지 않아도 됩니다." - -msgid "The physical network name with which the HA network can be created." -msgstr "HA 네트워크를 작성하는 데 사용할 수 있는 실제 네트워크 이름입니다. " - #, python-format msgid "The port '%s' was deleted" msgstr "포트 '%s'이(가) 삭제됨" @@ -1897,13 +1583,6 @@ msgstr "ML2 플러그인에 터널 IP 값이 필요함" msgid "Tunnel bridge to use." msgstr "사용할 터널 브릿지입니다." -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 카탈로그에서 검" -"색하며 공용, 내부 또는 관리 중 하나여야 합니다." - msgid "URL for connecting to designate" msgstr "지정하기 위해 연결할 URL" @@ -2022,13 +1701,6 @@ msgid "Use either --delta or relative revision, not both" msgstr "--델타 또는 상대적 개정판 중 하나 사용" 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 에이전트 노드에 설치되어야 합니다." - -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." @@ -2073,57 +1745,15 @@ msgstr "" "는 tc-tbf 매뉴얼을 참조하십시오." msgid "" -"When proxying metadata requests, Neutron signs the Instance-ID header with a " -"shared secret to prevent spoofing. You may select any string for a secret, " -"but it must match here and in the configuration used by the Nova Metadata " -"Server. NOTE: Nova uses the same config key, but in [neutron] section." -msgstr "" -"메타데이터 요청의 프록시 역할을 수행할 때 Neutron이 위조를 방지하기 위해 공" -"유 시크릿으로 Instance-ID 헤더에 서명합니다. 시크릿으로 임의의 문자열을 선택" -"할 수 있지만 여기에 있는 문자열 및 Nova Metadata Server에서 사용하는 구성과 " -"일치해야 합니다. 참고: Nova에서는 [neutron] 섹션에 있는 동일한 구성 키를 사용" -"합니다." - -msgid "" "Where to store Neutron state files. This directory must be writable by the " "agent." msgstr "" "Neutron 상태 파일을 저장할 위치. 에이전트가 이 디렉토리에 쓸 수 있어야 합니" "다." -msgid "" -"With IPv6, the network used for the external gateway does not need to have " -"an associated subnet, since the automatically assigned link-local address " -"(LLA) can be used. However, an IPv6 gateway address is needed for use as the " -"next-hop for the default route. If no IPv6 gateway address is configured " -"here, (and only then) the neutron router will be configured to get its " -"default route from router advertisements (RAs) from the upstream router; in " -"which case the upstream router must also be configured to send these RAs. " -"The ipv6_gateway, when configured, should be the LLA of the interface on the " -"upstream router. If a next-hop using a global unique address (GUA) is " -"desired, it needs to be done via a subnet allocated to the network and not " -"through this parameter. " -msgstr "" -"IPv6를 사용하면 자동으로 지정되는 링크 로컬 주소(LLA)를 사용할 수 있으므로 외" -"부 게이트웨이에 사용한 네트워크에 연관 서브넷이 필요하지 않습니다. 그러나 기" -"본 라우트의 다음 홉으로 사용할 IPv6 게이트웨이 주소가 필요합니다. 여기서 " -"IPv6 게이트웨이 주소를 구성하지 않으면(또한 이 경우에만)상위 라우터의 " -"RA(Router Advertisement)에서 해당 기본 라우트를 가져오도록 Neutron 라우터를 " -"구성할 수 있습니다. 이 경우 이러한 RA를 보내도록 상위 라우터를 구성할 수도 있" -"습니다. ipv6_gateway를 구성한 경우, 이 게이트웨이가 상위 라우터의 인터페이스" -"에 대한 LLA여야 합니다. 글로벌 고유 주소(GUA)를 사용하는 다음 합이 필요한 경" -"우, 이 매개변수가 아닌 네트워크에 할당된 서브넷을 통해 수행해야 합니다. " - msgid "You must implement __call__" msgstr "__call__을 구현해야 합니다. " -msgid "" -"You must provide a config file for bridge - either --config-file or " -"env[NEUTRON_TEST_CONFIG_FILE]" -msgstr "" -"브릿지에 대한 구성 파일, 즉 --config-file 또는 env[QUANTUM_TEST_CONFIG_FILE] " -"env[NEUTRON_TEST_CONFIG_FILE]" - msgid "You must provide a revision or relative delta" msgstr "개정판 또는 상대적 델타를 제공해야 함" diff --git a/neutron/locale/pt_BR/LC_MESSAGES/neutron.po b/neutron/locale/pt_BR/LC_MESSAGES/neutron.po index 238b06973c..bf2049fc03 100644 --- a/neutron/locale/pt_BR/LC_MESSAGES/neutron.po +++ b/neutron/locale/pt_BR/LC_MESSAGES/neutron.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: neutron VERSION\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2023-01-26 15:02+0000\n" +"POT-Creation-Date: 2023-05-15 17:54+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -135,25 +135,10 @@ msgstr "Inclui atributos de teste aos recursos principais." msgid "Agent %(id)s is not a L3 Agent or has been disabled" msgstr "O agente %(id)s não é um agente L3 ou foi desativado" -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 agent " -"until admin changes admin_state_up to True." -msgstr "" -"Agente inicia com admin_state_up=False quando enable_new_agents=False. No " -"caso, os recursos do usuário não serão planejados automaticamente para o " -"agente até que o administrador mude admin_state_up para True." - #, python-format msgid "Agent updated: %(payload)s" msgstr "Agente atualizado:%(payload)s" -msgid "Allow auto scheduling networks to DHCP agent." -msgstr "Permitir o planejamento automático de redes para o agente DHCP." - -msgid "Allow auto scheduling of routers to L3 agent." -msgstr "Permitir planejamento automático de roteadores para agente L3." - msgid "Allow running metadata proxy." msgstr "Permite executar proxy de metadados." @@ -167,10 +152,6 @@ msgstr "Permitir a criação de registros PTR" msgid "Allow the usage of the bulk API" msgstr "Permitir o uso da API em massa" -msgid "Allow to perform insecure SSL (https) requests to nova metadata" -msgstr "" -"Permita executar solicitações (https) de SSL inseguras para metadados nova" - msgid "" "Allows for serving metadata requests coming from a dedicated metadata access " "network whose CIDR is 169.254.169.254/16 (or larger prefix), and is " @@ -380,9 +361,6 @@ msgstr "" msgid "Cleanup resources of a specific agent type only." msgstr "Limpar recursos somente de um tipo de agente específico." -msgid "Client certificate for nova metadata api server." -msgstr "Certificado do cliente para o servidor da API de metadados nova." - msgid "" "Comma-separated list of <network_device>:<vfs_to_exclude> tuples, mapping " "network_device to the agent's node-specific list of virtual functions that " @@ -446,27 +424,10 @@ msgstr "" "Lista separada por vírgula dos servidores DNS que será utilizada como " "encaminhadores." -msgid "Command to execute" -msgstr "Comando a ser executado" - -msgid "Config file for interface driver (You may also use l3_agent.ini)" -msgstr "" -"Arquivo de configuração para driver de interface (também é possível usar " -"l3_agent.ini)" - #, python-format msgid "Conflicting value ethertype %(ethertype)s for CIDR %(cidr)s" msgstr "O valor conflitante ethertype %(ethertype)s para CIDR %(cidr)s" -msgid "" -"Controls whether the neutron security group API is enabled in the server. It " -"should be false when using no security groups or using the nova security " -"group API." -msgstr "" -"Controla se a API do grupo de segurança neutron está ativada no servidor. " -"Ele deve ser false quando não usa nenhum grupo de segurança ou usa a API do " -"grupo de segurança nova." - #, python-format msgid "Could not bind to %(host)s:%(port)s after trying for %(time)d seconds" msgstr "" @@ -522,13 +483,6 @@ msgstr "" "Número padrão de entradas RBAC permitido por locatário. Um valor negativo " "significa ilimitado." -msgid "" -"Default number of resource allowed per tenant. A negative value means " -"unlimited." -msgstr "" -"Número padrão de recurso permitido por locatário. Um valor negativo " -"significa ilimitado." - msgid "Default security group" msgstr "Grupo de segurança padrão" @@ -602,21 +556,6 @@ msgstr "O driver para intgração do DNS externa." msgid "Driver for security groups firewall in the L2 agent" msgstr "Driver para firewall para grupos de segurança no agente L2" -msgid "Driver to use for scheduling network to DHCP agent" -msgstr "Driver a ser usado para planejar a rede para o agente DHCP" - -msgid "Driver to use for scheduling router to a default L3 agent" -msgstr "Driver a ser usado para planejar o roteador para um agente L3 padrão" - -msgid "" -"Driver used for ipv6 prefix delegation. This needs to be an entry point " -"defined in the neutron.agent.linux.pd_drivers namespace. See setup.cfg for " -"entry points included with the neutron source." -msgstr "" -"Driver usado para delegação de prefixo ipv6. Este precisa ser um ponto de " -"entrada definido no namespace neutron.agent.linux.pd_drivers. Consulte setup." -"cfg para pontos de entrada incluídos com a origem neutron." - #, python-format msgid "" "Duplicate L3HARouterAgentPortBinding is created for router(s) %(router)s. " @@ -662,13 +601,6 @@ msgid "Enable SSL on the API server" msgstr "Habilite SSL no servidor de API" msgid "" -"Enable VXLAN on the agent. Can be enabled when agent is managed by ml2 " -"plugin using linuxbridge mechanism driver" -msgstr "" -"Ative o VXLAN no agente. Pode ser ativado quando o agente é gerenciado pelo " -"plug-in ml2 usando o driver do mecanismo linuxbridge" - -msgid "" "Enable services on an agent with admin_state_up False. If this option is " "False, when admin_state_up of an agent is turned False, services on it will " "be disabled. Agents with admin_state_up False are not selected for automatic " @@ -724,13 +656,6 @@ msgstr "" "Driver da extensão %(driver)s necessário para o plug-in de serviço " "%(service_plugin)s não localizado." -msgid "" -"Extension to use alongside ml2 plugin's l2population mechanism driver. It " -"enables the plugin to populate VXLAN forwarding table." -msgstr "" -"Extensão a ser usada ao lado do driver do mecanismo l2population do plug-in " -"ml2. Ela permite que o plug-in preencha a tabela de encaminhamento de VXLAN." - #, python-format msgid "Extension with alias %s does not exist" msgstr "A extensão com %s não existe" @@ -830,18 +755,6 @@ msgstr "" "O código do ICMP (port-range-max) %(value)s é fornecido, mas o tipo do ICMP " "(port-range-min) está ausente." -msgid "ID of network" -msgstr "ID da rede" - -msgid "ID of network to probe" -msgstr "ID da rede para análise" - -msgid "ID of probe port to delete" -msgstr "ID da porta da análise a ser excluída" - -msgid "ID of probe port to execute command" -msgstr "ID da porta da análise para executar comando" - msgid "ID of the router" msgstr "ID do roteador" @@ -904,19 +817,6 @@ msgid "Illegal IP version number" msgstr "Número de versão de IP ilegal" msgid "" -"In some cases the Neutron router is not present to provide the metadata IP " -"but the DHCP server can be used to provide this info. Setting this value " -"will force the DHCP server to append specific host routes to the DHCP " -"request. If this option is set, then the metadata service will be activated " -"for all the networks." -msgstr "" -"Em alguns casos, o roteador Neutron não está presente para fornecer o IP de " -"metadados, mas o servidor DHCP poderá ser usado para fornecer essas " -"informações. A configuração desse valor forçará o servidor DHCP a anexar " -"rotas de host específicas à solicitação DHCP. Se essa opção for configurada, " -"o serviço de metadados será ativado para todas as redes." - -msgid "" "Indicates that this L3 agent should also handle routers that do not have an " "external network gateway configured. This option should be True only for a " "single agent in a Neutron deployment, and may be False for all agents if all " @@ -955,12 +855,6 @@ msgstr "" msgid "Interface to monitor" msgstr "Interface para monitorar" -msgid "" -"Interval between checks of child process liveness (seconds), use 0 to disable" -msgstr "" -"Intervalo entre verificações de um processo-filho em tempo real (segundos), " -"use 0 para desativar" - msgid "Interval between two metering measures" msgstr "Intervalo entre duas medidas de medição" @@ -1036,14 +930,6 @@ msgid "Invalid value for port %(port)s" msgstr "Valor inválido para a porta %(port)s" msgid "" -"Iptables mangle mark used to mark ingress from external network. This mark " -"will be masked with 0xffff so that only the lower 16 bits will be used." -msgstr "" -"Marca de tratamento de Iptables usada para marcar ingresso de rede externa. " -"Essa marca será mascarada com 0xffff, de modo que apenas os 16 bits " -"inferiores serão usados." - -msgid "" "Iptables mangle mark used to mark metadata valid requests. This mark will be " "masked with 0xffff so that only the lower 16 bits will be used." msgstr "" @@ -1100,12 +986,6 @@ msgstr "Local de soquete de domínio UNIX de Proxy de Metadados" msgid "Location to store DHCP server config files." msgstr "Local para armazenar arquivos de configuração do servidor DHCP" -msgid "Location to store IPv6 PD files." -msgstr "Local para armazenar arquivos IPv6 PD." - -msgid "Location to store IPv6 RA config files" -msgstr "Local para armazenar arquivos de configuração RA IPv6" - msgid "Location to store child pid files" msgstr "Local para armazenar arquivos pid filhos" @@ -1178,9 +1058,6 @@ msgstr "Driver de medição" msgid "MinRtrAdvInterval setting for radvd.conf" msgstr "Configuração de MinRtrAdvInterval para o radvd.conf" -msgid "Minimize polling by monitoring ovsdb for interface changes." -msgstr "Minimizar pesquisa monitorando ovsdb para alterações da interface." - #, python-format msgid "Missing key in mapping: '%s'" msgstr "Chave ausente no mapeamento: '%s'" @@ -1194,22 +1071,6 @@ msgstr "" "o tráfego de transmissão para esse grupo multicast. Quando desconfigurado, " "desativa o modo VXLAN multicast." -msgid "" -"Multicast group(s) for vxlan interface. A range of group addresses may be " -"specified by using CIDR notation. Specifying a range allows different VNIs " -"to use different group addresses, reducing or eliminating spurious broadcast " -"traffic to the tunnel endpoints. To reserve a unique group for each possible " -"(24-bit) VNI, use a /8 such as 239.0.0.0/8. This setting must be the same on " -"all the agents." -msgstr "" -"Um ou mais grupos multicast para a interface VXLAN. Um intervalo de " -"endereços de grupo pode ser especificado usando a notação CIDR. Especificar " -"um intervalo permite que diferentes VNIs utilizem diferentes endereços de " -"grupo, reduzindo ou eliminando tráfego de transmissão falso para os " -"terminais do túnel. Para reservar um grupo exclusivo para cada VNI (24 bits) " -"possível, use um /8 como 239.0.0.0/8. Essa configuração deve ser a mesma em " -"todos os agentes." - #, python-format msgid "Multiple default providers for service %s" msgstr "Mútliplos provedores padrão para o serviço %s" @@ -1234,12 +1095,6 @@ msgstr "Deve especificar uma ou mais ações na adição ou modificação do flu msgid "Name of Open vSwitch bridge to use" msgstr "Nome da ponte Open vSwitch a ser usado" -msgid "" -"Name of nova region to use. Useful if keystone manages more than one region." -msgstr "" -"Nome da região do nova para utilização. Útil se keystone gerencia mais de " -"uma região." - msgid "Namespace of the router" msgstr "Namespace do roteador" @@ -1318,16 +1173,6 @@ msgid "Not allowed to manually remove a router from an agent in 'dvr' mode." msgstr "" "Não é permitido remover manualmente um roteador de um agente no modo 'dvr'." -msgid "" -"Number of DHCP agents scheduled to host a tenant network. If this number is " -"greater than 1, the scheduler automatically assigns multiple DHCP agents for " -"a given tenant network, providing high availability for DHCP service." -msgstr "" -"Número de agentes DHCP planejados para hospedar uma rede de um locatário. Se " -"esse número for maior que 1, o planejador designará automaticamente vários " -"agentes DHCP para uma determinada rede locatária, fornecendo alta " -"disponibilidade para o serviço DHCP." - msgid "Number of backlog requests to configure the metadata server socket with" msgstr "" "Número de solicitações de lista não processada para configurar o soquete do " @@ -1337,25 +1182,6 @@ msgid "Number of backlog requests to configure the socket with" msgstr "Número de requisições de backlog para configurar no socket" msgid "" -"Number of bits in an ipv4 PTR zone that will be considered network prefix. " -"It has to align to byte boundary. Minimum value is 8. Maximum value is 24. " -"As a consequence, range of values is 8, 16 and 24" -msgstr "" -"Número de bits em uma zona PTR IPV4 que será considerada como um prefixo de " -"rede. Ele deve estar alinhado ao limite de byte. O valor mínimo é 8. O valor " -"máximo é 24. Consequentemente, um intervalo de valores é 8, 16 e 24." - -msgid "" -"Number of bits in an ipv6 PTR zone that will be considered network prefix. " -"It has to align to nyble boundary. Minimum value is 4. Maximum value is 124. " -"As a consequence, range of values is 4, 8, 12, 16,..., 124" -msgstr "" -"Número de bits em uma zona PTR IPV6 que será considerada como um prefixo de " -"rede. Ele deve estar alinhado ao limite nyble. O valor mínimo é 4. O valor " -"máximo é 124. Consequentemente, um intervalo de valores é 4, 8, 12, " -"16, ...., 24." - -msgid "" "Number of floating IPs allowed per tenant. A negative value means unlimited." msgstr "" "Número de IPs flutuantes permitido por locatário. Um valor negativo " @@ -1377,13 +1203,6 @@ msgstr "" "Número de roteadores permitidos por locatário. Um valor negativo significa " "ilimitado." -msgid "" -"Number of seconds between sending events to nova if there are any events to " -"send." -msgstr "" -"Número de segundos entre o envio de eventos para nova se houver qualquer " -"evento a enviar." - msgid "Number of seconds to keep retrying to listen" msgstr "Número de segundos para continuar tentando escutar" @@ -1394,13 +1213,6 @@ msgstr "" "Número de grupos de segurança permitidos por locatário. Um valor negativo " "significa ilimitado." -msgid "" -"Number of security rules allowed per tenant. A negative value means " -"unlimited." -msgstr "" -"Número de regras de segurança permitidas por locatário. Um valor negativo " -"significa ilimitado." - msgid "Number of subnets allowed per tenant, A negative value means unlimited." msgstr "" "Número de sub-redes permitidas por locatário. Um valor negativo significa " @@ -1450,9 +1262,6 @@ msgstr "" msgid "Override the default dnsmasq settings with this file." msgstr "Sobrescreva as configurações padrão de dnsmasq com este arquivo." -msgid "Owner type of the device: network/compute" -msgstr "Tipo de proprietário do dispositivo: rede/cálculo" - msgid "POST requests are not supported on this resource." msgstr "Requisições POST não são suportadas neste recurso." @@ -1484,9 +1293,6 @@ msgstr "" msgid "Phase upgrade options do not accept revision specification" msgstr "Opções de upgrade de fase não aceitam especificação de revisão" -msgid "Ping timeout" -msgstr "Tempo Limite de Ping" - #, python-format msgid "Port %(id)s does not have fixed ip %(address)s" msgstr "A porta %(id)s não possui IP fixo %(address)s" @@ -1509,23 +1315,12 @@ msgstr "A delegação de prefixo só pode ser usada com sub-redes IPv6." msgid "Private key of client certificate." msgstr "Chave privada de certificado do cliente." -#, python-format -msgid "Probe %s deleted" -msgstr "Análise %s excluída" - -#, python-format -msgid "Probe created : %s " -msgstr "Análise criada: %s " - msgid "Process is already started" msgstr "O processo já está iniciado" msgid "Process is not running." msgstr "O processo não está em execução." -msgid "Protocol to access nova metadata, http or https" -msgstr "Protocolo para acessar os metadados de nova, http ou https" - #, python-format msgid "Provider name %(name)s is limited by %(len)s characters" msgstr "O nome do provedor %(name)s é limitado a %(len)s caracteres" @@ -1579,28 +1374,6 @@ msgstr "" "O repositório não contém arquivos HEAD para ramificações de contrato e de " "expansão." -msgid "" -"Representing the resource type whose load is being reported by the agent. " -"This can be \"networks\", \"subnets\" or \"ports\". When specified (Default " -"is networks), the server will extract particular load sent as part of its " -"agent configuration object from the agent report state, which is the number " -"of resources being consumed, at every report_interval.dhcp_load_type can be " -"used in combination with network_scheduler_driver = neutron.scheduler." -"dhcp_agent_scheduler.WeightScheduler When the network_scheduler_driver is " -"WeightScheduler, dhcp_load_type can be configured to represent the choice " -"for the resource being balanced. Example: dhcp_load_type=networks" -msgstr "" -"Representando o tipo de recurso cujo carregamento está sendo relatado pelo " -"agente. Isso pode ser \"redes\", \"sub-redes\" ou \"portas\". Quando " -"especificado (o padrão é redes), o servidor irá extrair carregamento " -"particular enviado como parte do seu objeto de configuração do agente do " -"relatório de estado do agente, que é o número de recursos sendo consumido, " -"em cada report_interval.dhcp_load_type pode ser usado em combinação com " -"network_scheduler_driver = neutron.scheduler.dhcp_agent_scheduler." -"WeightScheduler Quando o network_scheduler_driver é WeightScheduler, " -"dhcp_load_type pode ser configurado para representar a opção para o recurso " -"que está sendo balanceado. Exemplo: dhcp_load_type=networks" - msgid "Request Failed: internal server error while processing your request." msgstr "" "Falha de solicitação: erro do servidor interno ao processar sua solicitação." @@ -1679,13 +1452,6 @@ msgstr "" "Segundos entre os nós que relatam o estado para o servidor; deve ser menor " "que agent_down_time, melhor se for metade ou menos do que agent_down_time." -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 "" -"Segundos para considerar que o agente está inativo; deve ser no mínimo duas " -"vezes report_interval, para ter certeza de que o agente está inativo." - #, python-format msgid "Security Group %(id)s %(reason)s." msgstr "Grupo de segurança %(id)s %(reason)s." @@ -1723,16 +1489,6 @@ msgstr "" "valores valores %(values)s e representações de número inteiro [0 a 255] são " "suportados." -msgid "" -"Send notification to nova when port data (fixed_ips/floatingip) changes so " -"nova can update its cache." -msgstr "" -"Enviar notificação para nova quando dados da porta (fixed_ips/floatingip) " -"muda de modo que nova possa atualizar seu cache." - -msgid "Send notification to nova when port status changes" -msgstr "Enviar notificação para nova quando o status da porta muda" - #, python-format msgid "" "Service provider '%(provider)s' could not be found for service type " @@ -1749,21 +1505,6 @@ msgid "Service type %(service_type)s does not have a default service provider" msgstr "" "Tipo de serviço %(service_type)s não possui um provedor de serviço padrão" -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 "" -"Configure novo tempo limite em segundos para novas chamadas rpc depois que o " -"agente receber SIGTERM. Se o valor for configurado como 0, o tempo limite de " -"rpc não será alterado" - -msgid "" -"Set or un-set the don't fragment (DF) bit on outgoing IP packet carrying GRE/" -"VXLAN tunnel." -msgstr "" -"Configure ou desconfigure o bit don't fragment (DF) no pacote IP de saída " -"que transporta o túnel GRE/VXLAN." - msgid "Shared address scope can't be unshared" msgstr "O escopo de endereço compartilhado não pode ser descompartilhado" @@ -1780,9 +1521,6 @@ msgstr "A sub-rede para a interface do roteador deve ter um IP de gateway" msgid "Subnet pool has existing allocations" msgstr "O conjunto de sub-rede possui alocações existentes" -msgid "Subnet used for the l3 HA admin network." -msgstr "Sub-rede usada para a rede administrativa de alta disponibilidade l3." - msgid "" "System-wide flag to determine the type of router that tenants can create. " "Only admin can override." @@ -1796,9 +1534,6 @@ msgstr "Porta TCP usada pelo proxy de namespace de metadados Neutron." msgid "TCP Port used by Nova metadata server." msgstr "Porta TCP usada pelo servidor de metadados Nova." -msgid "TTL for vxlan interface protocol packets." -msgstr "TTL para pacotes de protocolo da interface vxlan." - #, python-format msgid "Tag %(tag)s could not be found." msgstr "A tag %(tag)s não pôde ser localizada." @@ -1815,22 +1550,6 @@ msgid "Tenant name for connecting to designate in admin context" msgstr "" "Nome do locatário para conexão ao Designate no contexto de admnistrador" -msgid "" -"The DHCP server can assist with providing metadata support on isolated " -"networks. Setting this value to True will cause the DHCP server to append " -"specific host routes to the DHCP request. The metadata service will only be " -"activated when the subnet does not contain any router port. The guest " -"instance must be configured to request host routes via DHCP (Option 121). " -"This option doesn't have any effect when force_metadata is set to True." -msgstr "" -"O servidor DHCP pode ajudar a fornecer suporte de metadados em redes " -"isoladas. Configurar esse valor para True fará com que o servidor DHCP anexe " -"rotas de host específicas à solicitação DHCP. O serviço de metadados será " -"ativado somente quando a sub-rede não contiver nenhuma porta do roteador. A " -"instância convidada deve ser configurada para solicitar rotas de host por " -"meio de DHCP (Opção 121). Essa opção não tem efeito algum quando " -"force_metadata estiver configurado para True." - msgid "The UDP port to use for VXLAN tunnels." msgstr "A porta UDP utilizada para túneis VXLAN." @@ -1853,30 +1572,12 @@ msgstr "" "permanecerão inalterados. Se o 4º octeto não for 00, ele também será " "utilizado, Os outros serão gerados aleatoriamente." -msgid "" -"The base mac address used for unique DVR instances by Neutron. The first 3 " -"octets will remain unchanged. If the 4th octet is not 00, it will also be " -"used. The others will be randomly generated. The 'dvr_base_mac' *must* be " -"different from 'base_mac' to avoid mixing them up with MAC's allocated for " -"tenant ports. A 4 octet example would be dvr_base_mac = fa:16:3f:4f:00:00. " -"The default is 3 octet" -msgstr "" -"O endereço mac base usado para instâncias DVR exclusivas pelo Neutron. Os " -"primeiros 3 octetos permanecerão inalterados. Se o quarto octeto não for 00, " -"ele também será usado. Os outros serão aleatoriamente gerados. O " -"'dvr_base_mac' *deve* ser diferente de 'base_mac' para evitar misturá-los " -"com os do MAC alocados para portas locatárias. Um exemplo de 4 octetos seria " -"dvr_base_mac = fa:16:3f:4f:00:00. O padrão é 3 octetos" - msgid "The core plugin Neutron will use" msgstr "O plug-in principal que o Neutron irá utilizar." msgid "The driver used to manage the DHCP server." msgstr "O driver usado para gerenciar o servidor DHCP." -msgid "The driver used to manage the virtual interface." -msgstr "Driver usado para gerenciar a interface virtual." - msgid "" "The email address to be used when creating PTR zones. If not specified, the " "email address will be admin@<dns_domain>" @@ -1885,54 +1586,15 @@ msgstr "" "endereço de e-mail será admin@<dns_domain>" msgid "" -"The maximum number of items returned in a single response, value was " -"'infinite' or negative integer means no limit" -msgstr "" -"O número máximo de itens retornados em uma única resposta, o valor era " -"'infinito' ou um número inteiro negativo significa que não há limite" - -msgid "" -"The network type to use when creating the HA network for an HA router. By " -"default or if empty, the first 'tenant_network_types' is used. This is " -"helpful when the VRRP traffic should use a specific network which is not the " -"default one." -msgstr "" -"O tipo de rede a ser usado ao criar a rede HA para um roteador HA. Por " -"padrão ou se em branco, o primeiro 'tenant_network_types' será usado. Isso é " -"útil quando o tráfego VRRP deve usar uma rede específica que não é a padrão." - -msgid "" "The number of seconds the agent will wait between polling for local device " "changes." msgstr "" "O número de segundos que o agente aguardará entre as pesquisas para mudanças " "do dispositivo local." -msgid "" -"The number of seconds to wait before respawning the ovsdb monitor after " -"losing communication with it." -msgstr "" -"O número de segundos a aguardar antes de reiniciar o monitor ovsdb após " -"perder comunicação com ele." - msgid "The number of sort_keys and sort_dirs must be same" msgstr "Os números de sort_keys e sort_dirs devem ser os mesmos" -msgid "" -"The path for API extensions. Note that this can be a colon-separated list of " -"paths. For example: api_extensions_path = extensions:/path/to/more/exts:/" -"even/more/exts. The __path__ of neutron.extensions is appended to this, so " -"if your extensions are in there you don't need to specify them here." -msgstr "" -"O caminho para extensões da API. Note que isso pode ser uma lista separada " -"por vírgula de caminhos. Por exemplo: api_extensions_path = extensions:/path/" -"to/more/exts:/even/more/exts. O __path__ of neutron.extensions é anexado a " -"isso, de modo que se suas extensões estiverem lá, não será necessário " -"especificá-las aqui. " - -msgid "The physical network name with which the HA network can be created." -msgstr "O nome da rede física com o qual a rede HA pode ser criada." - #, python-format msgid "The port '%s' was deleted" msgstr "A porta '%s' foi excluída" @@ -1986,13 +1648,6 @@ msgstr "Valor do IP do túnel necessário pelo plug-in ML2" msgid "Tunnel bridge to use." msgstr "Ponte do túnel a ser utilizada." -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 "" -"O tipo do terminal Nova a ser utilizado. Esse terminal será bloqueado no " -"catálogo de keystone e deverá ser público, interno ou de administração." - msgid "URL for connecting to designate" msgstr "URL para conexão ao Designate" @@ -2113,14 +1768,6 @@ msgid "Use either --delta or relative revision, not both" msgstr "Use --delta ou revisão relativa, não ambos" msgid "" -"Use ipset to speed-up the iptables based security groups. Enabling ipset " -"support requires that ipset is installed on L2 agent node." -msgstr "" -"Utilize ipset para acelerar os grupos de segurança baseados em iptables. " -"Para habilitar o suporte a ipset é necessário que o ipset esteja instalado " -"no nó do agente L2." - -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." @@ -2167,60 +1814,15 @@ msgstr "" "Consulte o manual tc-tbf para obter mais informações." msgid "" -"When proxying metadata requests, Neutron signs the Instance-ID header with a " -"shared secret to prevent spoofing. You may select any string for a secret, " -"but it must match here and in the configuration used by the Nova Metadata " -"Server. NOTE: Nova uses the same config key, but in [neutron] section." -msgstr "" -"Ao configurar o proxy de solicitações de metadados, o Neutron designa o " -"cabeçalho Instance-ID com um segredo compartilhado para evitar spoofing. É " -"possível selecionar qualquer sequência de um segredo, mas ela deverá " -"corresponder aqui e na configurada usada pelo Nova Metadata Server. NOTA: O " -"Nova usa a mesma chave de configuração, mas na seção [neutro]." - -msgid "" "Where to store Neutron state files. This directory must be writable by the " "agent." msgstr "" "Onde armazenar arquivos de estado Neutron. O agente deve ter permissão de " "escrita neste diretório." -msgid "" -"With IPv6, the network used for the external gateway does not need to have " -"an associated subnet, since the automatically assigned link-local address " -"(LLA) can be used. However, an IPv6 gateway address is needed for use as the " -"next-hop for the default route. If no IPv6 gateway address is configured " -"here, (and only then) the neutron router will be configured to get its " -"default route from router advertisements (RAs) from the upstream router; in " -"which case the upstream router must also be configured to send these RAs. " -"The ipv6_gateway, when configured, should be the LLA of the interface on the " -"upstream router. If a next-hop using a global unique address (GUA) is " -"desired, it needs to be done via a subnet allocated to the network and not " -"through this parameter. " -msgstr "" -"Com IPv6, a rede usada para o gateway externo não precisa ter um sub-rede " -"associada, pois o Link-local Address (LLA) designado automaticamente pode " -"ser usado. No entanto, um endereço do gateway IPv6 é necessário para ser " -"usado como o próximo hop para a rota padrão. Se nenhum endereço do gateway " -"IPv6 for configurado aqui, (somente então) o roteador neutron será " -"configurado para obter sua rota padrão de router advertisements (RAs) do " -"roteador de envio de dados; em cujo caso o roteador de envio de dados também " -"deve ser configurado para enviar esses RAs. O ipv6_gateway, quando " -"configurado, deve ser o LLA da interface no roteador de envio de dados. Se " -"um próximo hop usando um global unique address (GUA) for desejado, isso " -"precisará ser feito por meio de uma sub-rede alocada para a rede e não por " -"meio desse parâmetro. " - msgid "You must implement __call__" msgstr "Você deve implementar __call__" -msgid "" -"You must provide a config file for bridge - either --config-file or " -"env[NEUTRON_TEST_CONFIG_FILE]" -msgstr "" -"Você deve fornecer um arquivo de configuração para a ponte - --config-file " -"ou env[NEUTRON_TEST_CONFIG_FILE]" - msgid "You must provide a revision or relative delta" msgstr "Você deve fornecer uma revisão ou um delta relativo" diff --git a/neutron/locale/ru/LC_MESSAGES/neutron.po b/neutron/locale/ru/LC_MESSAGES/neutron.po index 5b76876cde..57de5d8346 100644 --- a/neutron/locale/ru/LC_MESSAGES/neutron.po +++ b/neutron/locale/ru/LC_MESSAGES/neutron.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: neutron VERSION\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2023-01-26 15:02+0000\n" +"POT-Creation-Date: 2023-05-15 17:54+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -134,26 +134,10 @@ msgstr "Добавляет атрибуты теста в базовые ресÑ msgid "Agent %(id)s is not a L3 Agent or has been disabled" msgstr "Агент %(id)s выключен или не является агентом L3" -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 agent " -"until admin changes admin_state_up to True." -msgstr "" -"Агент запускается с параметром admin_state_up=False, если включен параметр " -"enable_new_agents=False. В этом случае пользовательские ресурсы не будут " -"автоматически запланированы в агенте, пока администратор не изменит " -"значение параметра admin_state_up на True." - #, python-format msgid "Agent updated: %(payload)s" msgstr "Агент обновлен: %(payload)s" -msgid "Allow auto scheduling networks to DHCP agent." -msgstr "Разрешить автоматическое планирование сетей для агента DHCP." - -msgid "Allow auto scheduling of routers to L3 agent." -msgstr "Разрешить автоматическое планирование маршрутизаторов для агента L3." - msgid "Allow running metadata proxy." msgstr "Разрешить выполнение прокси метаданных." @@ -166,9 +150,6 @@ msgstr "Разрешить создание записей PTR" msgid "Allow the usage of the bulk API" msgstr "Разрешить использование Bulk API" -msgid "Allow to perform insecure SSL (https) requests to nova metadata" -msgstr "Разрешить незащищенные запросы SSL (https) метаданных nova" - msgid "" "Allows for serving metadata requests coming from a dedicated metadata access " "network whose CIDR is 169.254.169.254/16 (or larger prefix), and is " @@ -373,9 +354,6 @@ msgstr "" msgid "Cleanup resources of a specific agent type only." msgstr "Очистить ресурсы только для заданного типа агента." -msgid "Client certificate for nova metadata api server." -msgstr "Сертификат клиента для сервера API метаданных nova." - msgid "" "Comma-separated list of <network_device>:<vfs_to_exclude> tuples, mapping " "network_device to the agent's node-specific list of virtual functions that " @@ -438,27 +416,10 @@ msgstr "" "Разделенный запятыми список серверов DNS, которые будут использоваться для " "пересылки." -msgid "Command to execute" -msgstr "Выполняемая команда" - -msgid "Config file for interface driver (You may also use l3_agent.ini)" -msgstr "" -"Файл конфигурации для драйвера интерфейса (Можно также использовать l3_agent." -"ini)" - #, python-format msgid "Conflicting value ethertype %(ethertype)s for CIDR %(cidr)s" msgstr "Конфликтующее значение ethertype %(ethertype)s для CIDR %(cidr)s" -msgid "" -"Controls whether the neutron security group API is enabled in the server. It " -"should be false when using no security groups or using the nova security " -"group API." -msgstr "" -"Контролирует, включен ли API групп защиты neutron на сервере. Значение " -"должно быть false, когда группы защиты не используются или используется API " -"групп защиты nova." - #, python-format msgid "Could not bind to %(host)s:%(port)s after trying for %(time)d seconds" msgstr "" @@ -514,13 +475,6 @@ msgstr "" "Количество записей RBAC по умолчанию на одного арендатора. Отрицательное " "значение - без ограничений." -msgid "" -"Default number of resource allowed per tenant. A negative value means " -"unlimited." -msgstr "" -"Количество ресурсов по умолчанию на одного арендатора. Отрицательное " -"значение - не ограничено." - msgid "Default security group" msgstr "Группа защиты по умолчанию" @@ -592,23 +546,6 @@ msgstr "Драйвер для интеграции с внешним DNS." msgid "Driver for security groups firewall in the L2 agent" msgstr "Драйвер для брандмауэра групп защиты в агенте L2" -msgid "Driver to use for scheduling network to DHCP agent" -msgstr "Драйвер, используемый для планирования сети для агента DHCP" - -msgid "Driver to use for scheduling router to a default L3 agent" -msgstr "" -"Драйвер, используемый для планирования маршрутизатора для агента L3 по " -"умолчанию" - -msgid "" -"Driver used for ipv6 prefix delegation. This needs to be an entry point " -"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." - #, python-format msgid "" "Duplicate L3HARouterAgentPortBinding is created for router(s) %(router)s. " @@ -653,13 +590,6 @@ msgid "Enable SSL on the API server" msgstr "Разрешить применение SSL на сервере API" msgid "" -"Enable VXLAN on the agent. Can be enabled when agent is managed by ml2 " -"plugin using linuxbridge mechanism driver" -msgstr "" -"Активируйте VXLAN на агенте. Активация возможна, если агентом управляет " -"модуль ml2, использующий драйвер механизма linuxbridge" - -msgid "" "Enable services on an agent with admin_state_up False. If this option is " "False, when admin_state_up of an agent is turned False, services on it will " "be disabled. Agents with admin_state_up False are not selected for automatic " @@ -712,13 +642,6 @@ msgstr "" "Не найден драйвер расширения %(driver)s, необходимый для модуля службы " "%(service_plugin)s." -msgid "" -"Extension to use alongside ml2 plugin's l2population mechanism driver. It " -"enables the plugin to populate VXLAN forwarding table." -msgstr "" -"Расширение для использования наряду с драйвером механизма l2population " -"модуля ml2. Оно обеспечивает заполнение модулем таблицы пересылки VXLAN." - #, python-format msgid "Extension with alias %s does not exist" msgstr "Расширение с псевдонимом %s не существует" @@ -821,18 +744,6 @@ msgstr "" "Код ICMP (port-range-max) %(value)s указан, но тип ICMP (port-range-min) " "отсутствует." -msgid "ID of network" -msgstr "ИД сети" - -msgid "ID of network to probe" -msgstr "ИД сети для тестирования" - -msgid "ID of probe port to delete" -msgstr "ИД удаляемого тестового порта" - -msgid "ID of probe port to execute command" -msgstr "ИД тестового порта для выполнения команды" - msgid "ID of the router" msgstr "ИД маршрутизатора" @@ -896,18 +807,6 @@ msgid "Illegal IP version number" msgstr "Запрещенный номер версии IP" msgid "" -"In some cases the Neutron router is not present to provide the metadata IP " -"but the DHCP server can be used to provide this info. Setting this value " -"will force the DHCP server to append specific host routes to the DHCP " -"request. If this option is set, then the metadata service will be activated " -"for all the networks." -msgstr "" -"В некоторых ситуациях машрутизатор Neutron отсутствует и не предоставляет " -"метаданные для IP, но эту задачу решает сервер DHCP. Если задан этот " -"параметр, то сервер DHCP будет добавлять маршруты к хостам в запрос DHCP. С " -"этим параметром служба метаданных будет активирована для всех сетей." - -msgid "" "Indicates that this L3 agent should also handle routers that do not have an " "external network gateway configured. This option should be True only for a " "single agent in a Neutron deployment, and may be False for all agents if all " @@ -948,12 +847,6 @@ msgstr "" msgid "Interface to monitor" msgstr "Интерфейс для монитора" -msgid "" -"Interval between checks of child process liveness (seconds), use 0 to disable" -msgstr "" -"Интервал между проверками работы дочернего процесса (в секундах), 0 для " -"отключения" - msgid "Interval between two metering measures" msgstr "Интервал между двумя показателями измерений" @@ -1031,14 +924,6 @@ msgid "Invalid value for port %(port)s" msgstr "Недопустимое значение для порта %(port)s" msgid "" -"Iptables mangle mark used to mark ingress from external network. This mark " -"will be masked with 0xffff so that only the lower 16 bits will be used." -msgstr "" -"Пометка mangle в iptables применяется для пометки входа из внешней сети. Эта " -"пометка будет применяться с маской 0xffff для использования только младших " -"16 бит." - -msgid "" "Iptables mangle mark used to mark metadata valid requests. This mark will be " "masked with 0xffff so that only the lower 16 bits will be used." msgstr "" @@ -1095,12 +980,6 @@ msgstr "Расположение сокета домена UNIX прокси мÐ msgid "Location to store DHCP server config files." msgstr "Расположение для хранения файлов конфигурации сервера DHCP." -msgid "Location to store IPv6 PD files." -msgstr "Расположение для хранения файлов PD IPv6." - -msgid "Location to store IPv6 RA config files" -msgstr "Расположение для хранения файлов конфигурации RA IPv6" - msgid "Location to store child pid files" msgstr "Расположение для хранения дочерних файлов pid" @@ -1175,10 +1054,6 @@ msgstr "Драйвер измерения" msgid "MinRtrAdvInterval setting for radvd.conf" msgstr "Параметр MinRtrAdvInterval для radvd.conf" -msgid "Minimize polling by monitoring ovsdb for interface changes." -msgstr "" -"Минимизировать опрос путем мониторинга ovsdb на предмет изменений интерфейса." - #, python-format msgid "Missing key in mapping: '%s'" msgstr "Отсутствует ключ в отображении: '%s'" @@ -1192,22 +1067,6 @@ msgstr "" "широковещательный трафик направляется в эту группу. Если она не задана, то " "режим многоадресной передачи VXLAN выключен." -msgid "" -"Multicast group(s) for vxlan interface. A range of group addresses may be " -"specified by using CIDR notation. Specifying a range allows different VNIs " -"to use different group addresses, reducing or eliminating spurious broadcast " -"traffic to the tunnel endpoints. To reserve a unique group for each possible " -"(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. Если указан диапазон, то различные VNI смогут " -"использовать разные адреса группы, что снижает или даже исключает " -"интенсивный широковещательный трафик для конечных точек туннеля. Для того " -"чтобы зарезервировать уникальную группу для каждого возможного VNI (24 " -"бита), используйте формат /8, например, 239.0.0.0/8. Этот параметр должен " -"быть одинаковым во всех агентах." - #, python-format msgid "Multiple default providers for service %s" msgstr "Несколько поставщиков по умолчанию для службы %s" @@ -1232,12 +1091,6 @@ msgstr "" msgid "Name of Open vSwitch bridge to use" msgstr "Имя используемого моста Open vSwitch" -msgid "" -"Name of nova region to use. Useful if keystone manages more than one region." -msgstr "" -"Имя используемого региона nova. Необходимо, если keystone управляет " -"несколькими регионами." - msgid "Namespace of the router" msgstr "Пространство имен маршрутизатора" @@ -1312,16 +1165,6 @@ msgstr "Невозможно вручную присвоить маршрутиÐ msgid "Not allowed to manually remove a router from an agent in 'dvr' mode." msgstr "Невозможно вручную удалить маршрутизатор из агента в режиме 'dvr'." -msgid "" -"Number of DHCP agents scheduled to host a tenant network. If this number is " -"greater than 1, the scheduler automatically assigns multiple DHCP agents for " -"a given tenant network, providing high availability for DHCP service." -msgstr "" -"Число агентов DHCP, запланированных для управления сети арендатора. Если это " -"значение больше 1, планировщик автоматически присваивает несколько агентов " -"DHCP для заданной сети арендатора, обеспечивая высокую готовность службы " -"DHCP." - msgid "Number of backlog requests to configure the metadata server socket with" msgstr "" "Количество непереданных запросов для настройки сокета сервера метаданных" @@ -1330,24 +1173,6 @@ msgid "Number of backlog requests to configure the socket with" msgstr "Количество непереданных запросов для настройки сокета" msgid "" -"Number of bits in an ipv4 PTR zone that will be considered network prefix. " -"It has to align to byte boundary. Minimum value is 8. Maximum value is 24. " -"As a consequence, range of values is 8, 16 and 24" -msgstr "" -"Число разрядов в зоне PTR ipv4, которые будут обрабатываться как префикс " -"сети. Должно быть выравнено на границу байта. Минимальное значение: 8. " -"Максимальное значение: 24. Допустимые значения: 8, 16 и 24" - -msgid "" -"Number of bits in an ipv6 PTR zone that will be considered network prefix. " -"It has to align to nyble boundary. Minimum value is 4. Maximum value is 124. " -"As a consequence, range of values is 4, 8, 12, 16,..., 124" -msgstr "" -"Число разрядов в зоне PTR ipv6, которые будут обрабатываться как префикс " -"сети. Должно быть выравнено на границу полубайта. Минимальное значение: 4. " -"Максимальное значение: 124. Допустимые значения: 4, 8, 12, 16,..., 124" - -msgid "" "Number of floating IPs allowed per tenant. A negative value means unlimited." msgstr "" "Количество нефиксированных IP-адресов на одного арендатора. Отрицательное " @@ -1369,13 +1194,6 @@ msgstr "" "Количество маршрутизаторов на одного арендатора. Отрицательное значение - не " "ограничено." -msgid "" -"Number of seconds between sending events to nova if there are any events to " -"send." -msgstr "" -"Интервал, в секундах, между отправкой событий nova, если имеются события, " -"требующие отправки." - msgid "Number of seconds to keep retrying to listen" msgstr "Интервал (в секундах) для продолжения попыток приема" @@ -1386,13 +1204,6 @@ msgstr "" "Количество групп защиты на одного арендатора. Отрицательное значение - не " "ограничено." -msgid "" -"Number of security rules allowed per tenant. A negative value means " -"unlimited." -msgstr "" -"Количество правил защиты на одного арендатора. Отрицательное значение - не " -"ограничено." - msgid "Number of subnets allowed per tenant, A negative value means unlimited." msgstr "" "Количество подсетей на одного арендатора. Отрицательное значение - не " @@ -1444,9 +1255,6 @@ msgid "Override the default dnsmasq settings with this file." msgstr "" "Переопределите параметры по умолчанию для dnsmasq с помощью этого файла." -msgid "Owner type of the device: network/compute" -msgstr "Тип владельца устройства: network/compute" - msgid "POST requests are not supported on this resource." msgstr "Запросы POST не поддерживаются этим ресурсом." @@ -1477,9 +1285,6 @@ msgstr "Равноправный порт исправлений в мосте Ñ msgid "Phase upgrade options do not accept revision specification" msgstr "Опции обновления фазы не принимают спецификацию ревизии" -msgid "Ping timeout" -msgstr "Тайм-аут проверки связи" - #, python-format msgid "Port %(id)s does not have fixed ip %(address)s" msgstr "Порт %(id)s не имеет фиксированного IP-адреса %(address)s" @@ -1502,23 +1307,12 @@ msgstr "Делегирование префикса можно использоÐ msgid "Private key of client certificate." msgstr "Личный ключ сертификата клиента." -#, python-format -msgid "Probe %s deleted" -msgstr "Тест %s удален" - -#, python-format -msgid "Probe created : %s " -msgstr "Создан тест %s " - msgid "Process is already started" msgstr "Процесс уже запущен" msgid "Process is not running." msgstr "Процесс не запущен." -msgid "Protocol to access nova metadata, http or https" -msgstr "Протокол для доступа к метаданным nova (http или https)" - #, python-format msgid "Provider name %(name)s is limited by %(len)s characters" msgstr "Имя поставщика %(name)s, не более %(len)s символов" @@ -1569,28 +1363,6 @@ msgid "" "Repository does not contain HEAD files for contract and expand branches." msgstr "Хранилище не содержит файлы HEAD для ветвей contract и expand." -msgid "" -"Representing the resource type whose load is being reported by the agent. " -"This can be \"networks\", \"subnets\" or \"ports\". When specified (Default " -"is networks), the server will extract particular load sent as part of its " -"agent configuration object from the agent report state, which is the number " -"of resources being consumed, at every report_interval.dhcp_load_type can be " -"used in combination with network_scheduler_driver = neutron.scheduler." -"dhcp_agent_scheduler.WeightScheduler When the network_scheduler_driver is " -"WeightScheduler, dhcp_load_type can be configured to represent the choice " -"for the resource being balanced. Example: dhcp_load_type=networks" -msgstr "" -"Представление типа ресурса, о чьей загрузке сообщает агент. Это может быть " -"\"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 "" "Запрос не выполнен: при обработке запроса произошла внутренняя ошибка " @@ -1672,14 +1444,6 @@ msgstr "" "Значение должно быть меньше, чем agent_down_time, оптимально - не больше " "половины значения agent_down_time." -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, чтобы " -"убедиться в том, что агент выключен навсегда." - #, python-format msgid "Security Group %(id)s %(reason)s." msgstr "Группа защиты %(id)s %(reason)s." @@ -1716,16 +1480,6 @@ msgstr "" "Протокол правил группы защиты %(protocol)s не поддерживается. Поддерживаются " "значения %(values)s и целочисленные представления [0 - 255]." -msgid "" -"Send notification to nova when port data (fixed_ips/floatingip) changes so " -"nova can update its cache." -msgstr "" -"Отправить уведомление nova в случае изменения данных порта (fixed_ips/" -"floatingip), чтобы обеспечить обновление кэша nova." - -msgid "Send notification to nova when port status changes" -msgstr "Отправить уведомление nova в случае изменения состояния порта" - #, python-format msgid "" "Service provider '%(provider)s' could not be found for service type " @@ -1740,20 +1494,6 @@ msgstr "Служба для обработки делегирования пре msgid "Service type %(service_type)s does not have a default service provider" msgstr "Тип службы %(service_type)s не содержит поставщика службы по умолчанию" -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 "" -"Задать новый тайм-аут (в секундах) для новых вызовов rpc после получения " -"агентом сигнала SIGTERM. При значении 0 тайм-аут rpc не может быть изменен" - -msgid "" -"Set or un-set the don't fragment (DF) bit on outgoing IP packet carrying GRE/" -"VXLAN tunnel." -msgstr "" -"Установка/сброс бита Не разбивать на фрагменты (DF) в исходящем пакете IP, " -"несущем туннель GRE/VXLAN." - msgid "Shared address scope can't be unshared" msgstr "Для общей адресной области нельзя отменить совместное использование" @@ -1771,10 +1511,6 @@ msgstr "" msgid "Subnet pool has existing allocations" msgstr "Пул подсетей имеет существующие выделения" -msgid "Subnet used for the l3 HA admin network." -msgstr "" -"Подсеть, используемая для сети администрирования высокой готовности L3." - msgid "" "System-wide flag to determine the type of router that tenants can create. " "Only admin can override." @@ -1788,9 +1524,6 @@ msgstr "Порт TCP, применяемый прокси пространств msgid "TCP Port used by Nova metadata server." msgstr "Порт TCP, используемый сервером метаданных Nova." -msgid "TTL for vxlan interface protocol packets." -msgstr "TTL для пакетов протокола интерфейса vxlan." - #, python-format msgid "Tag %(tag)s could not be found." msgstr "Тег %(tag)s не найден." @@ -1811,21 +1544,6 @@ msgstr "" "Имя арендатора для подключения к назначенному объекту в административном " "контексте" -msgid "" -"The DHCP server can assist with providing metadata support on isolated " -"networks. Setting this value to True will cause the DHCP server to append " -"specific host routes to the DHCP request. The metadata service will only be " -"activated when the subnet does not contain any router port. The guest " -"instance must be configured to request host routes via DHCP (Option 121). " -"This option doesn't have any effect when force_metadata is set to True." -msgstr "" -"Сервер DHCP может помогать в получении метаданных в изолированных сетях. " -"Если параметру присвоено значение True, то сервер DHCP будет добавлять " -"маршруты к хостам в запрос DHCP. Служба метаданных активируется, только " -"когда подсеть не содержит портов маршрутизатора. Гостевой экземпляр должен " -"быть настроен для запросов маршрутов к хостам через DHCP (Option 121). Этот " -"параметр ни на что не влияет, если force_metadata задан равным True." - msgid "The UDP port to use for VXLAN tunnels." msgstr "Порт UDP, применяемый для туннелей VXLAN." @@ -1846,30 +1564,12 @@ msgstr "" "изменены. Если 4-й октет не равен 00, он тоже будет использоваться. " "Остальные будут созданы случайным образом." -msgid "" -"The base mac address used for unique DVR instances by Neutron. The first 3 " -"octets will remain unchanged. If the 4th octet is not 00, it will also be " -"used. The others will be randomly generated. The 'dvr_base_mac' *must* be " -"different from 'base_mac' to avoid mixing them up with MAC's allocated for " -"tenant ports. A 4 octet example would be dvr_base_mac = fa:16:3f:4f:00:00. " -"The default is 3 octet" -msgstr "" -"Базовый mac-адрес, используемый в Neutron для уникальных экземпляров DVR. " -"Первые 3 октета не будут изменены. Если 4-й октет не равен 00, он тоже будет " -"использоваться. Остальные будут созданы случайным образом. Параметр " -"'dvr_base_mac' *должен* отличаться от 'base_mac' для предотвращения " -"смешивания их с MAC-адресами, выделенными для портов арендатора. Пример 4 " -"октетов: dvr_base_mac = fa:16:3f:4f:00:00. ПО умолчанию используется 3 октета" - msgid "The core plugin Neutron will use" msgstr "Будет использоваться базовый модуль Neutron" msgid "The driver used to manage the DHCP server." msgstr "драйвер, используемый для управления сервером DHCP." -msgid "The driver used to manage the virtual interface." -msgstr "Драйвер, используемый для управления виртуальным интерфейсом." - msgid "" "The email address to be used when creating PTR zones. If not specified, the " "email address will be admin@<dns_domain>" @@ -1878,53 +1578,14 @@ msgstr "" "использоваться admin@<dns_domain>" msgid "" -"The maximum number of items returned in a single response, value was " -"'infinite' or negative integer means no limit" -msgstr "" -"Максимальное количество элементов, возвращаемых в одном ответе; значение " -"было 'infinite' или отрицательным целым, что означает бесконечное число" - -msgid "" -"The network type to use when creating the HA network for an HA router. By " -"default or if empty, the first 'tenant_network_types' is used. This is " -"helpful when the VRRP traffic should use a specific network which is not the " -"default one." -msgstr "" -"Тип сети при создании сети HA для маршрутизатора HA. По умолчанию (или при " -"пустом значении) используется первое значение 'tenant_network_types'. Такой " -"подход помогает, если поток данных VRRP должен использовать сеть, не " -"являющуюся стандартной." - -msgid "" "The number of seconds the agent will wait between polling for local device " "changes." msgstr "" "Интервал опроса агентом локальных устройств на предмет наличия изменений." -msgid "" -"The number of seconds to wait before respawning the ovsdb monitor after " -"losing communication with it." -msgstr "" -"Время ожидания, в секундах, повторного порождения монитора ovsdb после " -"потери соединения с ним." - msgid "The number of sort_keys and sort_dirs must be same" msgstr "Количество sort_keys и sort_dirs должно быть одинаковым" -msgid "" -"The path for API extensions. Note that this can be a colon-separated list of " -"paths. For example: api_extensions_path = extensions:/path/to/more/exts:/" -"even/more/exts. The __path__ of neutron.extensions is appended to this, so " -"if your extensions are in there you don't need to specify them here." -msgstr "" -"Путь для расширений API. Пути разделяются точкой с запятой. Пример: " -"api_extensions_path = extensions:/path/to/more/exts:/even/more/exts. " -"__path__ для расширений neutron добавляется автоматически, и если расширения " -"содержатся там, их не требуется указывать здесь." - -msgid "The physical network name with which the HA network can be created." -msgstr "Имя физической сети для создания сети HA." - #, python-format msgid "The port '%s' was deleted" msgstr "Порт '%s' был удален" @@ -1978,14 +1639,6 @@ msgstr "Для модуля ML2 требуется значение IP-адреÑ msgid "Tunnel bridge to use." msgstr "Используемый мост туннеля." -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, конечная точка может быть общедоступной, внутренней или " -"административной." - msgid "URL for connecting to designate" msgstr "URL для подключения к назначенному объекту" @@ -2105,13 +1758,6 @@ msgid "Use either --delta or relative revision, not both" msgstr "Используйте или --delta, или относительную ревизию, но не оба" 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." - -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." @@ -2161,60 +1807,15 @@ msgstr "" "дополнительной информацией обратитесь к руководству по tc-tbf." msgid "" -"When proxying metadata requests, Neutron signs the Instance-ID header with a " -"shared secret to prevent spoofing. You may select any string for a secret, " -"but it must match here and in the configuration used by the Nova Metadata " -"Server. NOTE: Nova uses the same config key, but in [neutron] section." -msgstr "" -"При проксировании запросов метаданных Neutron подписывает заголовок Instance-" -"ID общим секретным ключом для предотвращения подмены. Ключом может быть " -"любая строка, но она должна совпадать с указанной в конфигурации для сервера " -"метаданных Nova. Примечание: Nova использует тот же ключ конфигурации, но в " -"разделе [neutron]." - -msgid "" "Where to store Neutron state files. This directory must be writable by the " "agent." msgstr "" "Расположение хранения файлов состояния Neutron. Этот каталог должен быть " "доступен для записи агентом." -msgid "" -"With IPv6, the network used for the external gateway does not need to have " -"an associated subnet, since the automatically assigned link-local address " -"(LLA) can be used. However, an IPv6 gateway address is needed for use as the " -"next-hop for the default route. If no IPv6 gateway address is configured " -"here, (and only then) the neutron router will be configured to get its " -"default route from router advertisements (RAs) from the upstream router; in " -"which case the upstream router must also be configured to send these RAs. " -"The ipv6_gateway, when configured, should be the LLA of the interface on the " -"upstream router. If a next-hop using a global unique address (GUA) is " -"desired, it needs to be done via a subnet allocated to the network and not " -"through this parameter. " -msgstr "" -"При использовании IPv6 применяемой для внешнего шлюза сети не обязательно " -"иметь связанную подсеть, так как может быть использован автоматически " -"назначаемый адрес link-local (LLA). Однако, адрес шлюза IPv6 необходим в " -"качестве следующего узла для маршрута по умолчанию. Если адрес шлюза IPv6 не " -"указан здесь, (и только в этом случае) будет настроен маршрутизатор Neutron " -"для получения маршрута по умолчанию из объявлений маршрутизатора (RA) от " -"маршрутизатора выше по течению. В этом случае маршрутизатор выше по течению " -"должен быть также настроен для отправки этих RA. Когда указано значение " -"ipv6_gateway, оно должно указывать на LLA интерфейса маршрутизатора выше по " -"течению. Если следующий узел, использующийглобальный уникальный адрес (GUA), " -"является предпочитаем, это необходимо обеспечить посредством подсети, " -"выделенной для сети, а не с помощью этого параметра. " - msgid "You must implement __call__" 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]" - msgid "You must provide a revision or relative delta" msgstr "Необходимо указать ревизию или относительную дельта" diff --git a/neutron/locale/zh_CN/LC_MESSAGES/neutron.po b/neutron/locale/zh_CN/LC_MESSAGES/neutron.po index b5224f18ba..753d3bb389 100644 --- a/neutron/locale/zh_CN/LC_MESSAGES/neutron.po +++ b/neutron/locale/zh_CN/LC_MESSAGES/neutron.po @@ -18,7 +18,7 @@ msgid "" msgstr "" "Project-Id-Version: neutron VERSION\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2023-01-26 15:02+0000\n" +"POT-Creation-Date: 2023-05-15 17:54+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -135,25 +135,10 @@ msgstr "将测试属性添加至核心资源。" msgid "Agent %(id)s is not a L3 Agent or has been disabled" msgstr "代理 %(id)s 不是 L3 代理或已禁用" -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 agent " -"until admin changes admin_state_up to True." -msgstr "" -"当 enable_new_agents=False 时,代理将使用 admin_state_up=False 启动。在这种情" -"况下,将不会自动对代理调度用户的资源,直到管理员将 admin_state_up 更改为 " -"True 为止。" - #, python-format msgid "Agent updated: %(payload)s" msgstr "进程更新: %(payload)s" -msgid "Allow auto scheduling networks to DHCP agent." -msgstr "允许自动对 DHCP 代理调度网络。" - -msgid "Allow auto scheduling of routers to L3 agent." -msgstr "允许自动对 L3 代理调度路由器。" - msgid "Allow running metadata proxy." msgstr "允许运行 metadata代理" @@ -166,9 +151,6 @@ msgstr "允许创建 PTR 记录" msgid "Allow the usage of the bulk API" msgstr "允许使用成批 API" -msgid "Allow to perform insecure SSL (https) requests to nova metadata" -msgstr "允许对 nova 元数据执行非安全 SSL (HTTPS) 请求" - msgid "" "Allows for serving metadata requests coming from a dedicated metadata access " "network whose CIDR is 169.254.169.254/16 (or larger prefix), and is " @@ -365,9 +347,6 @@ msgstr "" msgid "Cleanup resources of a specific agent type only." msgstr "仅清除特定代理程序类型的资源。" -msgid "Client certificate for nova metadata api server." -msgstr "nova 元数据 API 服务器的客户机证书。" - msgid "" "Comma-separated list of <network_device>:<vfs_to_exclude> tuples, mapping " "network_device to the agent's node-specific list of virtual functions that " @@ -423,24 +402,10 @@ msgid "" "Comma-separated list of the DNS servers which will be used as forwarders." msgstr "将用作转发器的 DNS 服务器的逗号分隔列表。" -msgid "Command to execute" -msgstr "要执行的命令" - -msgid "Config file for interface driver (You may also use l3_agent.ini)" -msgstr "用于接口驱动程序的配置文件(还可使用 l3_agent.ini)" - #, python-format msgid "Conflicting value ethertype %(ethertype)s for CIDR %(cidr)s" msgstr "CIDR %(cidr)s 具有冲突值 ethertype %(ethertype)s " -msgid "" -"Controls whether the neutron security group API is enabled in the server. It " -"should be false when using no security groups or using the nova security " -"group API." -msgstr "" -"控制是否在服务器中启用了 neutron 安全组 API。未使用安全组或使用 nova安全组 " -"API 时,它应该为 false。" - #, python-format msgid "Could not bind to %(host)s:%(port)s after trying for %(time)d seconds" msgstr "在尝试%(time)d 秒之后不能绑定 %(host)s:%(port)s " @@ -484,11 +449,6 @@ msgid "" "unlimited." msgstr "每个租户允许的缺省 RBAC 条目数。负值表示无限制。" -msgid "" -"Default number of resource allowed per tenant. A negative value means " -"unlimited." -msgstr "每个租户允许的缺省资源数。负值表示无限。" - msgid "Default security group" msgstr "缺省安全组" @@ -558,20 +518,6 @@ msgstr "外部 DNS 集成的驱动程序。" msgid "Driver for security groups firewall in the L2 agent" msgstr "L2 代理程序中的安全组防火墙的驱动程序" -msgid "Driver to use for scheduling network to DHCP agent" -msgstr "要用于对 DHCP 代理调度网络的驱动程序" - -msgid "Driver to use for scheduling router to a default L3 agent" -msgstr "要用于对缺省 L3 代理调度路由器的驱动程序" - -msgid "" -"Driver used for ipv6 prefix delegation. This needs to be an entry point " -"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 源随附的入口点。" - #, python-format msgid "" "Duplicate L3HARouterAgentPortBinding is created for router(s) %(router)s. " @@ -613,13 +559,6 @@ msgid "Enable SSL on the API server" msgstr "在API 服务器上打开SSL" msgid "" -"Enable VXLAN on the agent. Can be enabled when agent is managed by ml2 " -"plugin using linuxbridge mechanism driver" -msgstr "" -"请在代理上启用 VXLAN。可在通过使用 linuxbridge 机制驱动程序由 ml2 插件管理代" -"理时启用" - -msgid "" "Enable services on an agent with admin_state_up False. If this option is " "False, when admin_state_up of an agent is turned False, services on it will " "be disabled. Agents with admin_state_up False are not selected for automatic " @@ -668,13 +607,6 @@ msgid "" "not found." msgstr "找不到服务插件 %(service_plugin)s 所需的扩展驱动程序 %(driver)s。" -msgid "" -"Extension to use alongside ml2 plugin's l2population mechanism driver. It " -"enables the plugin to populate VXLAN forwarding table." -msgstr "" -"要与 ml2 插件的 l2population 机制驱动程序一起使用的扩展。它使该插件能够填充 " -"VXLAN 转发表。" - #, python-format msgid "Extension with alias %s does not exist" msgstr "具有别名 %s 的扩展不存在" @@ -769,18 +701,6 @@ msgstr "" "已提供 ICMP 代码 (port-range-max) %(value)s,但缺少 ICMP 类型 (port-range-" "min)。" -msgid "ID of network" -msgstr "网络的标识" - -msgid "ID of network to probe" -msgstr "要探测的网络的标识" - -msgid "ID of probe port to delete" -msgstr "要删除的探测器端口的标识" - -msgid "ID of probe port to execute command" -msgstr "用于执行命令的探测器端口的标识" - msgid "ID of the router" msgstr "路由器ID" @@ -836,17 +756,6 @@ msgid "Illegal IP version number" msgstr "IP 版本号不合法" msgid "" -"In some cases the Neutron router is not present to provide the metadata IP " -"but the DHCP server can be used to provide this info. Setting this value " -"will force the DHCP server to append specific host routes to the DHCP " -"request. If this option is set, then the metadata service will be activated " -"for all the networks." -msgstr "" -"在某些情况下,没有 Neutron 路由器可提供元数据 IP,但 DHCP 服务器可用于提供此" -"信息。设置此值将强制 DHCP 服务器将特定主机路由追加至 DHCP 请求。如果设置了此" -"选项,那么将对所有网络激活此元数据服务。" - -msgid "" "Indicates that this L3 agent should also handle routers that do not have an " "external network gateway configured. This option should be True only for a " "single agent in a Neutron deployment, and may be False for all agents if all " @@ -881,10 +790,6 @@ msgstr "" msgid "Interface to monitor" msgstr "要监视的接口" -msgid "" -"Interval between checks of child process liveness (seconds), use 0 to disable" -msgstr "子进程活性检查之间的时间间隔(秒),使用 0 来进行禁用" - msgid "Interval between two metering measures" msgstr "在采取两种测量措施之间的时间间隔" @@ -954,13 +859,6 @@ msgid "Invalid value for port %(port)s" msgstr "端口 %(port)s 的值无效" msgid "" -"Iptables mangle mark used to mark ingress from external network. This mark " -"will be masked with 0xffff so that only the lower 16 bits will be used." -msgstr "" -"用来标记外部网络中的入口的 Iptables mangle 标记。将使用 0xffff 来屏蔽此标记," -"以便将仅使用低位的 16 位。" - -msgid "" "Iptables mangle mark used to mark metadata valid requests. This mark will be " "masked with 0xffff so that only the lower 16 bits will be used." msgstr "" @@ -1013,12 +911,6 @@ msgstr "元数据代理 UNIX 域套接字的位置" msgid "Location to store DHCP server config files." msgstr "用于存储 DHCP 服务器配置文件的位置。" -msgid "Location to store IPv6 PD files." -msgstr "用来存储 IPv6 PD 文件的位置。" - -msgid "Location to store IPv6 RA config files" -msgstr "用于存储 IPv6 RA 配置文件的位置" - msgid "Location to store child pid files" msgstr "用于存储子 pid 文件的位置" @@ -1088,9 +980,6 @@ msgstr "测量驱动程序" msgid "MinRtrAdvInterval setting for radvd.conf" msgstr "radvd.conf 的 MinRtrAdvInterval 设置" -msgid "Minimize polling by monitoring ovsdb for interface changes." -msgstr "请通过监视 ovsdb 以获取接口更改来最大程度地减少轮询。" - #, python-format msgid "Missing key in mapping: '%s'" msgstr "映射中缺少键:“%s”" @@ -1103,19 +992,6 @@ msgstr "" "VXLAN 的多点广播组。如果配置了此项,那么系统允许将所有广播流量发送至此多点广" "播组。如果保留为未配置,那么系统将禁用多点广播 VXLAN 方式。" -msgid "" -"Multicast group(s) for vxlan interface. A range of group addresses may be " -"specified by using CIDR notation. Specifying a range allows different VNIs " -"to use different group addresses, reducing or eliminating spurious broadcast " -"traffic to the tunnel endpoints. To reserve a unique group for each possible " -"(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 注释指定一定范围的组地址。指定范围允许" -"不同 VNI 使用不同组地址,从而减少或消除发送至通道端点的伪造广播流量。为对每个" -"可能的(24 位)VNI 保留唯一组,请使用 /8,例如,239.0.0.0/8。此设置在所有代理" -"程序上必须相同。" - #, python-format msgid "Multiple default providers for service %s" msgstr "对于服务 %s,存在多个缺省提供程序" @@ -1136,10 +1012,6 @@ msgstr "必须在添加或删除流时指定一个或多个操作" msgid "Name of Open vSwitch bridge to use" msgstr "要使用的已打开 vSwitch 网桥的名称" -msgid "" -"Name of nova region to use. Useful if keystone manages more than one region." -msgstr "要使用的 nova 区域的名称。如果 keystone 管理多个区域,那么这很有用。" - msgid "Namespace of the router" msgstr "路由器名字空间" @@ -1214,14 +1086,6 @@ msgstr "不允许以“dvr”方式将路由器手动分配给代理程序。" msgid "Not allowed to manually remove a router from an agent in 'dvr' mode." msgstr "不允许以“dvr”方式从代理程序手动移除路由器。" -msgid "" -"Number of DHCP agents scheduled to host a tenant network. If this number is " -"greater than 1, the scheduler automatically assigns multiple DHCP agents for " -"a given tenant network, providing high availability for DHCP service." -msgstr "" -"已调度的主管租户网络的 DHCP 代理数。如果此数目大于 1,那么调度程序会自动为所" -"给定的租户网络分配多个 DHCP 代理,从而为 DHCP 服务提供高可用性。" - msgid "Number of backlog requests to configure the metadata server socket with" msgstr "关于配置元数据服务器套接字的储备请求数" @@ -1229,22 +1093,6 @@ msgid "Number of backlog requests to configure the socket with" msgstr "积压许多配置socket的请求" msgid "" -"Number of bits in an ipv4 PTR zone that will be considered network prefix. " -"It has to align to byte boundary. Minimum value is 8. Maximum value is 24. " -"As a consequence, range of values is 8, 16 and 24" -msgstr "" -"ipv4 PTR 区域中将被视为网络前缀的位数。它必须符合字节限制。最小值为 8。最大值" -"为 24。因此,有效值包括:8、16 和 24。" - -msgid "" -"Number of bits in an ipv6 PTR zone that will be considered network prefix. " -"It has to align to nyble boundary. Minimum value is 4. Maximum value is 124. " -"As a consequence, range of values is 4, 8, 12, 16,..., 124" -msgstr "" -"ipv6 PTR 区域中将被视为网络前缀的位数。它必须符合字节限制。最小值为 4。最大值" -"为 124。因此,有效值包括:4,8,12,16,...,124。" - -msgid "" "Number of floating IPs allowed per tenant. A negative value means unlimited." msgstr "每个租户允许的浮动 IP 数。负值表示无限。" @@ -1258,11 +1106,6 @@ msgstr "每个租户允许的端口数。负值表示无限。" msgid "Number of routers allowed per tenant. A negative value means unlimited." msgstr "每个租户允许的路由器数。负值表示无限。" -msgid "" -"Number of seconds between sending events to nova if there are any events to " -"send." -msgstr "前后两次将事件发送至 nova 的间隔秒数(如果有事件要发送)。" - msgid "Number of seconds to keep retrying to listen" msgstr "若干秒保持重试监听" @@ -1271,11 +1114,6 @@ msgid "" "unlimited." msgstr "每个租户允许的安全组数。负值表示无限。" -msgid "" -"Number of security rules allowed per tenant. A negative value means " -"unlimited." -msgstr "每个租户允许的安全性规则数。负值表示无限。" - msgid "Number of subnets allowed per tenant, A negative value means unlimited." msgstr "每个租户允许的子网数。负值表示无限。" @@ -1317,9 +1155,6 @@ msgstr "" msgid "Override the default dnsmasq settings with this file." msgstr "使用此文件覆盖缺省 dnsmasq 设置。" -msgid "Owner type of the device: network/compute" -msgstr "设备的所有者类型如下:网络/计算" - msgid "POST requests are not supported on this resource." msgstr "POST 请求在此资源上不受支持。" @@ -1349,9 +1184,6 @@ msgstr "隧道网桥中的同级补丁端口(对于集成网桥)。" msgid "Phase upgrade options do not accept revision specification" msgstr "阶段升级选项不接受修订规范" -msgid "Ping timeout" -msgstr "Ping 超时" - #, python-format msgid "Port %(id)s does not have fixed ip %(address)s" msgstr "端口 %(id)s 没有固定 ip %(address)s" @@ -1373,23 +1205,12 @@ msgstr "前缀授权只能用于 IPv6 子网。" msgid "Private key of client certificate." msgstr "客户机证书的专用密钥。" -#, python-format -msgid "Probe %s deleted" -msgstr "已删除探测器 %s" - -#, python-format -msgid "Probe created : %s " -msgstr "已创建探测器:%s " - msgid "Process is already started" msgstr "进程已经启动" msgid "Process is not running." msgstr "进程未运行" -msgid "Protocol to access nova metadata, http or https" -msgstr "用于访问 nova 元数据的协议(HTTP 或 HTTPS)" - #, python-format msgid "Provider name %(name)s is limited by %(len)s characters" msgstr "供应商名称 %(name)s 被限制为不超过 %(len)s 个字符" @@ -1436,25 +1257,6 @@ msgid "" "Repository does not contain HEAD files for contract and expand branches." msgstr "存储库未包含用于合同分支和扩展分支的 HEAD 文件。" -msgid "" -"Representing the resource type whose load is being reported by the agent. " -"This can be \"networks\", \"subnets\" or \"ports\". When specified (Default " -"is networks), the server will extract particular load sent as part of its " -"agent configuration object from the agent report state, which is the number " -"of resources being consumed, at every report_interval.dhcp_load_type can be " -"used in combination with network_scheduler_driver = neutron.scheduler." -"dhcp_agent_scheduler.WeightScheduler When the network_scheduler_driver is " -"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" - msgid "Request Failed: internal server error while processing your request." msgstr "请求失败:在处理请求时,发生内部服务器错误。" @@ -1528,13 +1330,6 @@ msgstr "" "节点向服务器报告状态的间隔秒数;应该小于 agent_down_time,最好小于 " "agent_down_time 或是它的一半。" -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 的两倍,以确保代理已正常关" -"闭。" - #, python-format msgid "Security Group %(id)s %(reason)s." msgstr "安全组 %(id)s %(reason)s。" @@ -1570,16 +1365,6 @@ msgstr "" "安全组规则协议 %(protocol)s 不受支持。只有协议值 %(values)s 和整数表示 [0 到 " "255] 受支持。" -msgid "" -"Send notification to nova when port data (fixed_ips/floatingip) changes so " -"nova can update its cache." -msgstr "" -"当端口数据(固定 IP/floatingip)更改时,将通知发送至 nova,以便 nova 可更新其" -"高速缓存。" - -msgid "Send notification to nova when port status changes" -msgstr "当端口状态更改时,将通知发送至 nova" - #, python-format msgid "" "Service provider '%(provider)s' could not be found for service type " @@ -1593,18 +1378,6 @@ msgstr "用来处理 DHCPv6 前缀授权的服务。" msgid "Service type %(service_type)s does not have a default service provider" msgstr "服务类型 %(service_type)s 没有缺省服务提供程序" -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 "" -"在代理接收到 SIGTERM 之后,为新的 RPC 调用设置新超时(以秒计)。如果值设置为 " -"0,那么 RPC 超时将不更改" - -msgid "" -"Set or un-set the don't fragment (DF) bit on outgoing IP packet carrying GRE/" -"VXLAN tunnel." -msgstr "在承载 GRE/VXLAN 隧道的出局 IP 包上设置或取消设置不分段 (DF) 位。" - msgid "Shared address scope can't be unshared" msgstr "无法取消共享已共享的地址范围" @@ -1621,9 +1394,6 @@ msgstr "路由器接口的子网必须具有网关 IP" msgid "Subnet pool has existing allocations" msgstr "子网池具有现有分配" -msgid "Subnet used for the l3 HA admin network." -msgstr "用于 l3 HA 管理网络的子网。" - msgid "" "System-wide flag to determine the type of router that tenants can create. " "Only admin can override." @@ -1635,9 +1405,6 @@ msgstr "TCP 端口已由 Neutron 元数据名称空间代理使用。" msgid "TCP Port used by Nova metadata server." msgstr "Nova 元数据服务器使用的 TCP 端口。" -msgid "TTL for vxlan interface protocol packets." -msgstr "用于 vxlan 接口协议包的 TTL。" - #, python-format msgid "Tag %(tag)s could not be found." msgstr "找不到标记 %(tag)s。" @@ -1652,19 +1419,6 @@ msgstr "管理员上下文中要指定的连接租户标识" msgid "Tenant name for connecting to designate in admin context" msgstr "管理员上下文中要指定的连接租户名" -msgid "" -"The DHCP server can assist with providing metadata support on isolated " -"networks. Setting this value to True will cause the DHCP server to append " -"specific host routes to the DHCP request. The metadata service will only be " -"activated when the subnet does not contain any router port. The guest " -"instance must be configured to request host routes via DHCP (Option 121). " -"This option doesn't have any effect when force_metadata is set to True." -msgstr "" -"DHCP 服务器可帮助在隔离网络上提供元数据支持。将此值设置为 True 将导致 DHCP 服" -"务器将特定主机路由追加至 DHCP 请求。仅当子网未包含任何路由器端口时,才会激活" -"元数据服务。访客实例必须配置为通过 DHCP 请求主机路由(选项 121)。如果 " -"force_metadata 设置为 True,那么此选项没有任何效果。" - msgid "The UDP port to use for VXLAN tunnels." msgstr "UDP端口用于VXLAN隧道" @@ -1684,28 +1438,12 @@ msgstr "" "基本 MAC 地址 Neutron 将用于 VIF。前 3 个八位元将保持不变。如果第 4 个八位元" "并非 00,那么也将使用该八位元。将随机生成其他八位元。" -msgid "" -"The base mac address used for unique DVR instances by Neutron. The first 3 " -"octets will remain unchanged. If the 4th octet is not 00, it will also be " -"used. The others will be randomly generated. The 'dvr_base_mac' *must* be " -"different from 'base_mac' to avoid mixing them up with MAC's allocated for " -"tenant ports. A 4 octet example would be dvr_base_mac = fa:16:3f:4f:00:00. " -"The default is 3 octet" -msgstr "" -"由 Neutron 用于唯一 DVR 实例的基本 MAC 地址。前三个八位元将保持不变。如果第四" -"个八位元不为 00,那么也将使用该八位元。将随机生成其他八位元。“dvr_base_mac”必" -"须不同于“base_mac”,以避免将它们与为租户端口分配的 MAC 混合使用。以下是一个具" -"有 4 个八位元的示例:dvr_base_mac = fa:16:3f:4f:00:00。缺省值为 3 个八位元" - msgid "The core plugin Neutron will use" msgstr "Neutron 将使用的核心插件" msgid "The driver used to manage the DHCP server." msgstr "用于管理 DHCP 服务器的驱动程序。" -msgid "The driver used to manage the virtual interface." -msgstr "用于管理虚拟接口的驱动程序。" - msgid "" "The email address to be used when creating PTR zones. If not specified, the " "email address will be admin@<dns_domain>" @@ -1714,47 +1452,13 @@ msgstr "" "admin@<dns_domain>" msgid "" -"The maximum number of items returned in a single response, value was " -"'infinite' or negative integer means no limit" -msgstr "在单个响应中返回的最大项数,值为“无限”或负整数表示无限制" - -msgid "" -"The network type to use when creating the HA network for an HA router. By " -"default or if empty, the first 'tenant_network_types' is used. This is " -"helpful when the VRRP traffic should use a specific network which is not the " -"default one." -msgstr "" -"为 HA 路由器创建 HA 网络时要使用的网络类型。缺省情况下,或者如果网络类型为" -"空,那么将使用第一个“tenant_network_types”。这在 VRRP 流量应使用特定网络(该" -"网络不是缺省网络)时很有帮助。" - -msgid "" "The number of seconds the agent will wait between polling for local device " "changes." msgstr "在轮询本地设备更改之间,代理将等待的秒数。" -msgid "" -"The number of seconds to wait before respawning the ovsdb monitor after " -"losing communication with it." -msgstr "在与 ovsdb 监视器失去通信联系之后重新衍生该监视器之前要等待的秒数。" - msgid "The number of sort_keys and sort_dirs must be same" msgstr "sort_keys 的数字与 sort_dirs 的数字必须相同" -msgid "" -"The path for API extensions. Note that this can be a colon-separated list of " -"paths. For example: api_extensions_path = extensions:/path/to/more/exts:/" -"even/more/exts. The __path__ of neutron.extensions is appended to this, so " -"if your extensions are in there you don't need to specify them here." -msgstr "" -"API 扩展的路径。请注意,它可能是路径的冒号分隔列表。例如:" -"api_extensions_path = extensions:/path/to/more/exts:/even/more/exts。neutron." -"extensions 的 __path__ 将追加至此项之后,所以,如果扩展位于该处,那么不需要在" -"此处指定它们。" - -msgid "The physical network name with which the HA network can be created." -msgstr "可以用来创建 HA 网络的物理网络名称。" - #, python-format msgid "The port '%s' was deleted" msgstr "已删除端口“%s”" @@ -1805,13 +1509,6 @@ msgstr "ML2 插件需要隧道 IP 值" msgid "Tunnel bridge to use." msgstr "要使用的隧道网桥。" -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 目录中查找此端点,值应该为 " -"public、internal 或 admin 的其中之一。" - msgid "URL for connecting to designate" msgstr "要指定的连接 URL" @@ -1926,13 +1623,6 @@ msgid "Use either --delta or relative revision, not both" msgstr "请使用 --delta 或者相关修订版,但是不能同时指定这两者" 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 以加速基于安全组的 iptable。启用 ipset 支持要求该 ipset 安装在 L2 " -"代理程序节点上。" - -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." @@ -1975,49 +1665,13 @@ msgstr "" "多信息。" msgid "" -"When proxying metadata requests, Neutron signs the Instance-ID header with a " -"shared secret to prevent spoofing. You may select any string for a secret, " -"but it must match here and in the configuration used by the Nova Metadata " -"Server. NOTE: Nova uses the same config key, but in [neutron] section." -msgstr "" -"代理元数据请求时,Neutron 会使用共享密钥签署 Instance-ID 头以避免电子诈骗。可" -"选择任何字符串作为密钥,但此处的密钥必须与 Nova Metadata Server 使用的配置中" -"的密钥相匹配。注意:Nova 使用同一配置密钥,但在 [neutron] 节中。" - -msgid "" "Where to store Neutron state files. This directory must be writable by the " "agent." msgstr "用于存储 Neutron 状态文件的位置。此目录对于代理必须为可写。" -msgid "" -"With IPv6, the network used for the external gateway does not need to have " -"an associated subnet, since the automatically assigned link-local address " -"(LLA) can be used. However, an IPv6 gateway address is needed for use as the " -"next-hop for the default route. If no IPv6 gateway address is configured " -"here, (and only then) the neutron router will be configured to get its " -"default route from router advertisements (RAs) from the upstream router; in " -"which case the upstream router must also be configured to send these RAs. " -"The ipv6_gateway, when configured, should be the LLA of the interface on the " -"upstream router. If a next-hop using a global unique address (GUA) is " -"desired, it needs to be done via a subnet allocated to the network and not " -"through this parameter. " -msgstr "" -"对于 IPv6,用于外部网关的网络不需要具备相关联的子网,因为可以使用自动指定的链" -"路本地地址 (LLA)。但是,需要 IPv6 网关地址用作缺省路由的下一个路由器。如果此" -"处未配置 IPv6 网关地址,那么将配置 Neutron 路由器,以从上游的路由器中获取路由" -"器广告(RA)中的缺省路由;在这种情况下,还必须配置上游路由器以发送这些 RA。配" -"置了 ipv6_gateway 时,ipv6_gateway 应为上游路由器上的接口的 LLA。如果需要下一" -"个使用全局唯一地址 (GUA) 的路由器,那么它需要通过分配给该网络的子网来完成,而" -"不是通过此参数来完成。" - msgid "You must implement __call__" 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]" - msgid "You must provide a revision or relative delta" msgstr "必须提供修订或相对变化量" diff --git a/neutron/locale/zh_TW/LC_MESSAGES/neutron.po b/neutron/locale/zh_TW/LC_MESSAGES/neutron.po index f529f3283e..1c2cca322d 100644 --- a/neutron/locale/zh_TW/LC_MESSAGES/neutron.po +++ b/neutron/locale/zh_TW/LC_MESSAGES/neutron.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: neutron VERSION\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2023-01-26 15:02+0000\n" +"POT-Creation-Date: 2023-05-15 17:54+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -125,25 +125,10 @@ msgstr "將測試屬性新增至核心資源。" msgid "Agent %(id)s is not a L3 Agent or has been disabled" msgstr "代理程式 %(id)s 不是 L3 代理程式或者已停用" -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 agent " -"until admin changes admin_state_up to True." -msgstr "" -"當 enable_new_agents=False 時,代理程式從 admin_state_up=False 開始。在這種情" -"況下,不會將使用者的資源自動排程到代理程式,直到管理者將 admin_state_up 變更" -"為 True 為止。" - #, python-format msgid "Agent updated: %(payload)s" msgstr "已更新代理程式:%(payload)s" -msgid "Allow auto scheduling networks to DHCP agent." -msgstr "容許自動將網路排程到 DHCP 代理程式。" - -msgid "Allow auto scheduling of routers to L3 agent." -msgstr "容許自動將路由器排定到 L3 代理程式。" - msgid "Allow running metadata proxy." msgstr "容許執行 meta 資料 Proxy。" @@ -156,9 +141,6 @@ msgstr "容許建立 PTR 記錄" msgid "Allow the usage of the bulk API" msgstr "容許使用主體 API" -msgid "Allow to perform insecure SSL (https) requests to nova metadata" -msgstr "容許對 Nova meta 資料執行不安全的 SSL (HTTPS) 要求" - msgid "" "Allows for serving metadata requests coming from a dedicated metadata access " "network whose CIDR is 169.254.169.254/16 (or larger prefix), and is " @@ -351,9 +333,6 @@ msgstr "" msgid "Cleanup resources of a specific agent type only." msgstr "只清除特定代理程式類型的資源。" -msgid "Client certificate for nova metadata api server." -msgstr "Nova meta 資料 API 伺服器的用戶端憑證。" - msgid "" "Comma-separated list of <network_device>:<vfs_to_exclude> tuples, mapping " "network_device to the agent's node-specific list of virtual functions that " @@ -409,24 +388,10 @@ msgid "" "Comma-separated list of the DNS servers which will be used as forwarders." msgstr "將用來作為轉遞程式的 DNS 伺服器逗點區隔清單。" -msgid "Command to execute" -msgstr "要執行的指令" - -msgid "Config file for interface driver (You may also use l3_agent.ini)" -msgstr "介面驅動程式的配置檔(您也可使用 l3_agent.ini)" - #, python-format msgid "Conflicting value ethertype %(ethertype)s for CIDR %(cidr)s" msgstr "CIDR %(cidr)s 的乙太網路類型 %(ethertype)s 值有衝突" -msgid "" -"Controls whether the neutron security group API is enabled in the server. It " -"should be false when using no security groups or using the nova security " -"group API." -msgstr "" -"控制是否在伺服器中啟用 Neutron 安全群組 API。當不使用安全群組時或者使用 Nova " -"安全群組 API 時,它應該是 false。" - #, python-format msgid "Could not bind to %(host)s:%(port)s after trying for %(time)d seconds" msgstr "嘗試 %(time)d 秒後仍無法連結至 %(host)s:%(port)s" @@ -472,11 +437,6 @@ msgid "" "unlimited." msgstr "每個承租人所容許的 RBAC 項目數目。負數值表示無限制。" -msgid "" -"Default number of resource allowed per tenant. A negative value means " -"unlimited." -msgstr "每個承租人所容許的預設資源數目。負數值表示無限制。" - msgid "Default security group" msgstr "預設安全群組" @@ -544,20 +504,6 @@ msgstr "用於外部 DNS 整合的驅動程式。" msgid "Driver for security groups firewall in the L2 agent" msgstr "L2 代理程式中安全群組防火牆的驅動程式" -msgid "Driver to use for scheduling network to DHCP agent" -msgstr "用於將網路排程到 DHCP 代理程式的驅動程式" - -msgid "Driver to use for scheduling router to a default L3 agent" -msgstr "用於將路由器排程到預設 L3 代理程式的驅動程式" - -msgid "" -"Driver used for ipv6 prefix delegation. This needs to be an entry point " -"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 來源隨附的進入點。" - #, python-format msgid "" "Duplicate L3HARouterAgentPortBinding is created for router(s) %(router)s. " @@ -599,13 +545,6 @@ msgid "Enable SSL on the API server" msgstr "在 API 伺服器上啟用 SSL" 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" - -msgid "" "Enable services on an agent with admin_state_up False. If this option is " "False, when admin_state_up of an agent is turned False, services on it will " "be disabled. Agents with admin_state_up False are not selected for automatic " @@ -653,13 +592,6 @@ msgid "" "not found." msgstr "找不到服務外掛程式 %(service_plugin)s 所需的延伸驅動程式 %(driver)s。" -msgid "" -"Extension to use alongside ml2 plugin's l2population mechanism driver. It " -"enables the plugin to populate VXLAN forwarding table." -msgstr "" -"與 ML2 外掛程式的 l2population 機制驅動程式一起使用的延伸。它支援該外掛程式將" -"資料移入 VXLAN 轉遞表格。" - #, python-format msgid "Extension with alias %s does not exist" msgstr "別名為 %s 的延伸不存在" @@ -754,18 +686,6 @@ msgstr "" "提供了 ICMP 代碼 (port-range-max) %(value)s,但遺漏了 ICMP 類型(port-range-" "min)。" -msgid "ID of network" -msgstr "網路的 ID" - -msgid "ID of network to probe" -msgstr "要探測的網路 ID" - -msgid "ID of probe port to delete" -msgstr "要刪除的探針埠 ID" - -msgid "ID of probe port to execute command" -msgstr "要執行指令的探針埠 ID" - msgid "ID of the router" msgstr "路由器 ID" @@ -821,17 +741,6 @@ msgid "Illegal IP version number" msgstr "無效的 IP 版本號碼" msgid "" -"In some cases the Neutron router is not present to provide the metadata IP " -"but the DHCP server can be used to provide this info. Setting this value " -"will force the DHCP server to append specific host routes to the DHCP " -"request. If this option is set, then the metadata service will be activated " -"for all the networks." -msgstr "" -"在部分情況下,Neutron 路由器未呈現以提供 meta 資料 IP,但 DHCP 伺服器可用於提" -"供此資訊。設定此值會強制讓 DHCP 伺服器將特定的主機路線附加至 DHCP 要求。如果" -"設定此選項,則將對所有網路啟動 meta 資料服務。" - -msgid "" "Indicates that this L3 agent should also handle routers that do not have an " "external network gateway configured. This option should be True only for a " "single agent in a Neutron deployment, and may be False for all agents if all " @@ -866,10 +775,6 @@ msgstr "" msgid "Interface to monitor" msgstr "要監視的介面" -msgid "" -"Interval between checks of child process liveness (seconds), use 0 to disable" -msgstr "子程序存活檢查之間的間隔(秒),使用 0 以停用" - msgid "Interval between two metering measures" msgstr "兩次計量測量之間的間隔" @@ -940,13 +845,6 @@ msgid "Invalid value for port %(port)s" msgstr "埠 %(port)s 的值無效" msgid "" -"Iptables mangle mark used to mark ingress from external network. This mark " -"will be masked with 0xffff so that only the lower 16 bits will be used." -msgstr "" -"用於標示外部網路中入口的 iptables 破壞標記。此標記將以 0xffff 進行遮罩,以便" -"只使用較低的 16 位元。" - -msgid "" "Iptables mangle mark used to mark metadata valid requests. This mark will be " "masked with 0xffff so that only the lower 16 bits will be used." msgstr "" @@ -999,12 +897,6 @@ msgstr "meta 資料 Proxy UNIX 網域 Socket 的位置" msgid "Location to store DHCP server config files." msgstr "DHCP 伺服器配置檔的儲存位置。" -msgid "Location to store IPv6 PD files." -msgstr "用於儲存 IPv6 PD 檔的位置。" - -msgid "Location to store IPv6 RA config files" -msgstr "用於儲存 IPv6 RA 配置檔的位置" - msgid "Location to store child pid files" msgstr "子項 PID 檔案的儲存位置" @@ -1075,9 +967,6 @@ msgstr "計量驅動程式" msgid "MinRtrAdvInterval setting for radvd.conf" msgstr "radvd.conf 的 MinRtrAdvInterval 設定" -msgid "Minimize polling by monitoring ovsdb for interface changes." -msgstr "透過監視 OVSDB 是否有介面變更,將輪詢減至最少。" - #, python-format msgid "Missing key in mapping: '%s'" msgstr "對映中遺漏了索引鍵:'%s'" @@ -1090,19 +979,6 @@ msgstr "" "VXLAN 的多重播送群組。當已配置時,容許將所有廣播資料流量傳送至此多重播送群" "組。當保持未配置時,將停用多重播送 VXLAN 模式。" -msgid "" -"Multicast group(s) for vxlan interface. A range of group addresses may be " -"specified by using CIDR notation. Specifying a range allows different VNIs " -"to use different group addresses, reducing or eliminating spurious broadcast " -"traffic to the tunnel endpoints. To reserve a unique group for each possible " -"(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 表示法來指定群組位址的範圍。指定一個" -"範圍會容許不同的 VNI 使用不同的群組位址,以減少或刪除傳送至通道端點的虛假廣播" -"資料流量。如果要為每一個可能的(24 位元)VNI 保留一個唯一群組,請使用 /8(例" -"如 239.0.0.0/8)。在所有代理程式上,此設定必須相同。" - #, python-format msgid "Multiple default providers for service %s" msgstr "服務 %s 的多個預設提供者" @@ -1123,10 +999,6 @@ msgstr "必須對流程新增作業或修改作業指定一個以上的動作" msgid "Name of Open vSwitch bridge to use" msgstr "要使用的 Open vSwitch 橋接器名稱" -msgid "" -"Name of nova region to use. Useful if keystone manages more than one region." -msgstr "要使用的 Nova 區域名稱。如果 Keystone 管理多個區域,則很有用。" - msgid "Namespace of the router" msgstr "路由器名稱空間" @@ -1201,14 +1073,6 @@ msgstr "不容許將路由器手動指派給處於 'dvr' 模式的代理程式〠msgid "Not allowed to manually remove a router from an agent in 'dvr' mode." msgstr "不容許從處於 'dvr' 模式的代理程式中手動移除路由器。" -msgid "" -"Number of DHCP agents scheduled to host a tenant network. If this number is " -"greater than 1, the scheduler automatically assigns multiple DHCP agents for " -"a given tenant network, providing high availability for DHCP service." -msgstr "" -"已排程管理承租人網路的 DHCP 代理程式數目。如果此數目大於 1,則排程器會自動為" -"給定的承租人網路指派多個 DHCP 代理程式,為 DHCP 服務提供高可用性。" - msgid "Number of backlog requests to configure the metadata server socket with" msgstr "要配置給 meta 資料伺服器 Socket 的待辦事項要求數目" @@ -1216,22 +1080,6 @@ msgid "Number of backlog requests to configure the socket with" msgstr "要配置給 Socket 的待辦事項要求數目" msgid "" -"Number of bits in an ipv4 PTR zone that will be considered network prefix. " -"It has to align to byte boundary. Minimum value is 8. Maximum value is 24. " -"As a consequence, range of values is 8, 16 and 24" -msgstr "" -"將被視為網路字首之 IPv4 PTR 區域中的位元數目。它必須與位元組界限對齊。下限值" -"為 8。上限值為 24。因此,值的範圍是 8、16 和 24" - -msgid "" -"Number of bits in an ipv6 PTR zone that will be considered network prefix. " -"It has to align to nyble boundary. Minimum value is 4. Maximum value is 124. " -"As a consequence, range of values is 4, 8, 12, 16,..., 124" -msgstr "" -"將被視為網路字首之 IPv6 PTR 區域中的位元數目。它必須與 nyble 界限對齊。下限值" -"為 4。上限值為 124。因此,值的範圍是 4、8、12、16、...、124" - -msgid "" "Number of floating IPs allowed per tenant. A negative value means unlimited." msgstr "每個承租人所容許的浮動 IP 數目。負數值表示無限制。" @@ -1245,11 +1093,6 @@ msgstr "每個承租人所容許的埠數目。負數值表示無限制。" msgid "Number of routers allowed per tenant. A negative value means unlimited." msgstr "每個承租人所容許的路由器數目。負數值表示無限制。" -msgid "" -"Number of seconds between sending events to nova if there are any events to " -"send." -msgstr "兩次將事件傳送至 Nova 之間的秒數(如果有任何事件要傳送)。" - msgid "Number of seconds to keep retrying to listen" msgstr "不斷重試接聽的秒數" @@ -1258,11 +1101,6 @@ msgid "" "unlimited." msgstr "每個承租人所容許的安全群組數目。負數值表示無限制。" -msgid "" -"Number of security rules allowed per tenant. A negative value means " -"unlimited." -msgstr "每個承租人所容許的安全規則數目。負數值表示無限制。" - msgid "Number of subnets allowed per tenant, A negative value means unlimited." msgstr "每個承租人所容許的子網路數目。負數值表示無限制。" @@ -1305,9 +1143,6 @@ msgstr "" msgid "Override the default dnsmasq settings with this file." msgstr "使用此檔案來置換預設 dnsmasq 設定。" -msgid "Owner type of the device: network/compute" -msgstr "裝置的擁有者類型:網路/計算" - msgid "POST requests are not supported on this resource." msgstr "此資源上不支援 POST 要求。" @@ -1337,9 +1172,6 @@ msgstr "通道橋接器中用於整合橋接器的同層級修補程式埠。" msgid "Phase upgrade options do not accept revision specification" msgstr "階段升級選項不接受修訂規格" -msgid "Ping timeout" -msgstr "連通測試逾時值" - #, python-format msgid "Port %(id)s does not have fixed ip %(address)s" msgstr "埠 %(id)s 沒有固定 IP %(address)s" @@ -1360,23 +1192,12 @@ msgstr "字首委派只能與 IPv6 子網路搭配使用。" msgid "Private key of client certificate." msgstr "用戶端憑證的私密金鑰。" -#, python-format -msgid "Probe %s deleted" -msgstr "已刪除探針 %s" - -#, python-format -msgid "Probe created : %s " -msgstr "已建立探針:%s " - msgid "Process is already started" msgstr "程序已啟動" msgid "Process is not running." msgstr "程序不在執行中。" -msgid "Protocol to access nova metadata, http or https" -msgstr "用於存取 Nova meta 資料的通訊協定:HTTP 或 HTTPS" - #, python-format msgid "Provider name %(name)s is limited by %(len)s characters" msgstr "提供者名稱 %(name)s 最多只能包含 %(len)s 個字元" @@ -1422,25 +1243,6 @@ msgid "" "Repository does not contain HEAD files for contract and expand branches." msgstr "儲存庫不含合約及延伸分支的 HEAD 檔。" -msgid "" -"Representing the resource type whose load is being reported by the agent. " -"This can be \"networks\", \"subnets\" or \"ports\". When specified (Default " -"is networks), the server will extract particular load sent as part of its " -"agent configuration object from the agent report state, which is the number " -"of resources being consumed, at every report_interval.dhcp_load_type can be " -"used in combination with network_scheduler_driver = neutron.scheduler." -"dhcp_agent_scheduler.WeightScheduler When the network_scheduler_driver is " -"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=網路" - msgid "Request Failed: internal server error while processing your request." msgstr "要求失敗:處理要求時發生內部伺服器錯誤。" @@ -1514,13 +1316,6 @@ msgstr "" "兩個節點將狀態報告給伺服器的間隔秒數;應該小於 agent_down_time;如果是 " "agent_down_time 的一半或者小於 agent_down_time,則最佳。" -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 的兩倍,以確保代理程式" -"已永久關閉。" - #, python-format msgid "Security Group %(id)s %(reason)s." msgstr "安全群組 %(id)s %(reason)s。" @@ -1556,16 +1351,6 @@ msgstr "" "不支援安全群組規則通訊協定 %(protocol)s。僅支援通訊協定值 %(values)s 和整數表" "示法 [0 到 255]。" -msgid "" -"Send notification to nova when port data (fixed_ips/floatingip) changes so " -"nova can update its cache." -msgstr "" -"埠資料 (fixed_ips/floatingip) 變更時,將通知傳送至 Nova,以便 Nova 可以更新其" -"快取。" - -msgid "Send notification to nova when port status changes" -msgstr "埠狀態變更時,將通知傳送至 Nova" - #, python-format msgid "" "Service provider '%(provider)s' could not be found for service type " @@ -1579,20 +1364,6 @@ msgstr "用於處理 DHCPv6 字首委派的服務。" msgid "Service type %(service_type)s does not have a default service provider" msgstr "服務類型 %(service_type)s 不具有預設服務提供者" -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 "" -"在代理程式接收 SIGTERM 之後為新 RPC 呼叫設定新逾時(以秒為單位)。如果值設定" -"為 0,RPC 逾時將不會變更" - -msgid "" -"Set or un-set the don't fragment (DF) bit on outgoing IP packet carrying GRE/" -"VXLAN tunnel." -msgstr "" -"在帶有 GRE/VXLAN 通道的送出 IP 封包上,設定或取消設定「不劃分片段 (DF)」位" -"元。" - msgid "Shared address scope can't be unshared" msgstr "無法將已共用的位址範圍取消共用" @@ -1609,9 +1380,6 @@ msgstr "路由器介面的子網路必須具有閘道 IP" msgid "Subnet pool has existing allocations" msgstr "子網路儲存區具有現有的配置" -msgid "Subnet used for the l3 HA admin network." -msgstr "用於 l3 HA 管理網路的子網路。" - msgid "" "System-wide flag to determine the type of router that tenants can create. " "Only admin can override." @@ -1623,9 +1391,6 @@ msgstr "Neutron meta 資料名稱空間 Proxy 所使用的 TCP 埠。" msgid "TCP Port used by Nova metadata server." msgstr "Nova meta 資料伺服器所使用的 TCP 埠。" -msgid "TTL for vxlan interface protocol packets." -msgstr "VXLAN 介面通訊協定封包的 TTL。" - #, python-format msgid "Tag %(tag)s could not be found." msgstr "找不到標記 %(tag)s。" @@ -1640,19 +1405,6 @@ msgstr "用於連接以在管理環境定義中指定的租戶 ID" msgid "Tenant name for connecting to designate in admin context" msgstr "用於連接以在管理環境定義中指定的租戶名稱" -msgid "" -"The DHCP server can assist with providing metadata support on isolated " -"networks. Setting this value to True will cause the DHCP server to append " -"specific host routes to the DHCP request. The metadata service will only be " -"activated when the subnet does not contain any router port. The guest " -"instance must be configured to request host routes via DHCP (Option 121). " -"This option doesn't have any effect when force_metadata is set to True." -msgstr "" -"DHCP 伺服器可透過在隔離網路上提供 meta 資料支援進行協助。將此值設為 True 會導" -"致 DHCP 伺服器將特定的主機路線附加至 DHCP 要求。僅當子網路不包含任何路由器埠" -"時,才啟動 meta 資料服務。訪客實例必須配置成透過 DHCP 來要求主機路線(選項 " -"121)。將 force_metadata 設為 True 時,這個選項沒有任何效果。" - msgid "The UDP port to use for VXLAN tunnels." msgstr "要用於 VXLAN 通道的 UDP 埠。" @@ -1672,29 +1424,12 @@ msgstr "" "Neutron 將用於 VIF 的基本 MAC 位址。前 3 個八位元組將保持不變。如果第 4 個八" "位元組不是 00,則也將使用該八位元組。其他各項將隨機產生。" -msgid "" -"The base mac address used for unique DVR instances by Neutron. The first 3 " -"octets will remain unchanged. If the 4th octet is not 00, it will also be " -"used. The others will be randomly generated. The 'dvr_base_mac' *must* be " -"different from 'base_mac' to avoid mixing them up with MAC's allocated for " -"tenant ports. A 4 octet example would be dvr_base_mac = fa:16:3f:4f:00:00. " -"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 " -"個八位元組" - msgid "The core plugin Neutron will use" msgstr "Neutron 將使用的核心外掛程式" msgid "The driver used to manage the DHCP server." msgstr "用於管理 DHCP 伺服器的驅動程式。" -msgid "The driver used to manage the virtual interface." -msgstr "用於管理虛擬介面的驅動程式。" - msgid "" "The email address to be used when creating PTR zones. If not specified, the " "email address will be admin@<dns_domain>" @@ -1703,47 +1438,13 @@ msgstr "" "admin@<dns_domain>" msgid "" -"The maximum number of items returned in a single response, value was " -"'infinite' or negative integer means no limit" -msgstr "在單一回應中傳回的項目數上限,值為 'infinite' 或負整數時表示無限制" - -msgid "" -"The network type to use when creating the HA network for an HA router. By " -"default or if empty, the first 'tenant_network_types' is used. This is " -"helpful when the VRRP traffic should use a specific network which is not the " -"default one." -msgstr "" -"為 HA 路由器建立 HA 網路時要使用的網路類型。依預設或者在空白的情況下,將使用" -"第一個 'tenant_network_types'。當 VRRP 資料流量應該使用的特定網路不是預設網路" -"時,這很有用。" - -msgid "" "The number of seconds the agent will wait between polling for local device " "changes." msgstr "輪詢本端裝置變更之間代理程式將等待的秒數。" -msgid "" -"The number of seconds to wait before respawning the ovsdb monitor after " -"losing communication with it." -msgstr "與 OVSDB 監視器的通訊中斷後重新大量產生OVSDB 監視器之前等待的秒數。" - msgid "The number of sort_keys and sort_dirs must be same" msgstr "sort_key 數目及 sort_dir 數目必須相同" -msgid "" -"The path for API extensions. Note that this can be a colon-separated list of " -"paths. For example: api_extensions_path = extensions:/path/to/more/exts:/" -"even/more/exts. The __path__ of neutron.extensions is appended to this, so " -"if your extensions are in there you don't need to specify them here." -msgstr "" -"API 延伸的路徑。請注意,這可以是分號區隔的路徑清單。例如:" -"api_extensions_path = extensions:/path/to/more/exts:/even/more/exts。已將 " -"neutron.extensions 的 __path__ 附加到此項,所以如果您的延伸在這裡,則不需要在" -"這裡指定它們。" - -msgid "The physical network name with which the HA network can be created." -msgstr "建立 HA 網路時可以使用的實體網路名稱。" - #, python-format msgid "The port '%s' was deleted" msgstr "已刪除埠 '%s'" @@ -1794,13 +1495,6 @@ msgstr "ML2 外掛程式需要的通道 IP 值" msgid "Tunnel bridge to use." msgstr "要使用的通道橋接器。" -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 型錄予以查閱,並且應該是共用、" -"內部或管理的其中一個。" - msgid "URL for connecting to designate" msgstr "用於連接以指定的 URL" @@ -1916,13 +1610,6 @@ msgid "Use either --delta or relative revision, not both" msgstr "使用 --delta 或相對修訂,但不要同時使用兩者" 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 支援需要在 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." @@ -1965,50 +1652,13 @@ msgstr "" "tbf 手冊。" msgid "" -"When proxying metadata requests, Neutron signs the Instance-ID header with a " -"shared secret to prevent spoofing. You may select any string for a secret, " -"but it must match here and in the configuration used by the Nova Metadata " -"Server. NOTE: Nova uses the same config key, but in [neutron] section." -msgstr "" -"對 meta 資料要求執行 Proxy 動作時,Neutron 會使用共用密碼來簽署 Instance-ID " -"標頭,以防止盜用。您可以選取任何字串用作密碼,但該字串在此處以及在 Nova meta " -"資料伺服器使用的配置中必須相符。附註:Nova 使用相同的配置金鑰,但卻在 " -"[neutron] 區段中。" - -msgid "" "Where to store Neutron state files. This directory must be writable by the " "agent." msgstr "Neutron 狀態檔的儲存位置。此目錄必須可以由代理程式寫入。" -msgid "" -"With IPv6, the network used for the external gateway does not need to have " -"an associated subnet, since the automatically assigned link-local address " -"(LLA) can be used. However, an IPv6 gateway address is needed for use as the " -"next-hop for the default route. If no IPv6 gateway address is configured " -"here, (and only then) the neutron router will be configured to get its " -"default route from router advertisements (RAs) from the upstream router; in " -"which case the upstream router must also be configured to send these RAs. " -"The ipv6_gateway, when configured, should be the LLA of the interface on the " -"upstream router. If a next-hop using a global unique address (GUA) is " -"desired, it needs to be done via a subnet allocated to the network and not " -"through this parameter. " -msgstr "" -"如果使用 IPv6,則用於外部閘道的網路不需要具有相關聯的子網路,因為可以使用自動" -"指派的鏈結本端位址 (LLA)。但是,IPv6 閘道位址需要用作預設路由的下一個中繼站。" -"如果未在這裡配置 IPv6 閘道位址,(且僅當那時)則將會配置 Neutron 路由器以從上" -"游路由器的路由器通告 (RA) 中取得其預設路由;在該情況下,也必須配置上游路由器" -"以傳送這些 RA。ipv6_gateway(如果已配置)應為上游路由器介面的 LLA。如果需要使" -"用廣域唯一位址 (GUA) 的下一個中繼站,則需要透過配置給網路的子網路來執行此配" -"置,而不是透過此參數。" - msgid "You must implement __call__" 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]" - msgid "You must provide a revision or relative delta" msgstr "必須提供修訂或相對差異" diff --git a/neutron/objects/db/api.py b/neutron/objects/db/api.py index 482728c314..8ece717d99 100644 --- a/neutron/objects/db/api.py +++ b/neutron/objects/db/api.py @@ -30,19 +30,19 @@ def _get_filter_query(obj_cls, context, query_field=None, query_limit=None, return query -@db_api.CONTEXT_READER def get_object(obj_cls, context, **kwargs): - return _get_filter_query(obj_cls, context, **kwargs).first() + with db_api.CONTEXT_READER.using(context): + return _get_filter_query(obj_cls, context, **kwargs).first() -@db_api.CONTEXT_READER def count(obj_cls, context, query_field=None, query_limit=None, **kwargs): - if not query_field and obj_cls.primary_keys: - query_field = obj_cls.primary_keys[0] - if query_field in obj_cls.fields_need_translation: - query_field = obj_cls.fields_need_translation[query_field] - return _get_filter_query(obj_cls, context, query_field=query_field, - query_limit=query_limit, **kwargs).count() + with db_api.CONTEXT_READER.using(context): + if not query_field and obj_cls.primary_keys: + query_field = obj_cls.primary_keys[0] + if query_field in obj_cls.fields_need_translation: + query_field = obj_cls.fields_need_translation[query_field] + return _get_filter_query(obj_cls, context, query_field=query_field, + query_limit=query_limit, **kwargs).count() def _kwargs_to_filters(**kwargs): diff --git a/neutron/objects/port/extensions/port_hints.py b/neutron/objects/port/extensions/port_hints.py new file mode 100644 index 0000000000..a9fd1c793f --- /dev/null +++ b/neutron/objects/port/extensions/port_hints.py @@ -0,0 +1,53 @@ +# Copyright 2023 Ericsson Software Technology +# +# 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. + +from neutron_lib.objects import common_types + +from neutron.db.models import port_hints +from neutron.objects import base + + +@base.NeutronObjectRegistry.register +class PortHints(base.NeutronDbObject): + # Version 1.0: Initial version + VERSION = '1.0' + + db_model = port_hints.PortHints + + primary_keys = ['port_id'] + + fields = { + 'port_id': common_types.UUIDField(), + 'hints': common_types.DictOfMiscValuesField(), + } + + foreign_keys = {'Port': {'port_id': 'id'}} + + @classmethod + def modify_fields_to_db(cls, fields): + result = super(PortHints, cls).modify_fields_to_db(fields) + if 'hints' in result: + # dump field into string, set '' if empty '{}' or None + result['hints'] = ( + cls.filter_to_json_str(result['hints'], default='')) + return result + + @classmethod + def modify_fields_from_db(cls, db_obj): + fields = super(PortHints, cls).modify_fields_from_db(db_obj) + if 'hints' in fields: + # load string from DB into dict, set None if hints is '' + fields['hints'] = ( + cls.load_json_from_str(fields['hints'])) + return fields diff --git a/neutron/objects/ports.py b/neutron/objects/ports.py index 462d86944c..e9fd61b38e 100644 --- a/neutron/objects/ports.py +++ b/neutron/objects/ports.py @@ -336,7 +336,8 @@ class Port(base.NeutronDbObject): # Version 1.5: Added qos_network_policy_id field # Version 1.6: Added numa_affinity_policy field # Version 1.7: Added port_device field - VERSION = '1.7' + # Version 1.8: Added hints field + VERSION = '1.8' db_model = models_v2.Port @@ -370,6 +371,9 @@ class Port(base.NeutronDbObject): 'fixed_ips': obj_fields.ListOfObjectsField( 'IPAllocation', nullable=True ), + 'hints': obj_fields.ObjectField( + 'PortHints', nullable=True + ), # TODO(ihrachys): consider converting to boolean 'security': obj_fields.ObjectField( 'PortSecurity', nullable=True @@ -407,6 +411,7 @@ class Port(base.NeutronDbObject): 'distributed_bindings', 'dns', 'fixed_ips', + 'hints', 'numa_affinity_policy', 'qos_policy_id', 'qos_network_policy_id', @@ -610,6 +615,8 @@ class Port(base.NeutronDbObject): primitive.pop('numa_affinity_policy', None) if _target_version < (1, 7): primitive.pop('device_profile', None) + if _target_version < (1, 8): + primitive.pop('hints', None) @classmethod @db_api.CONTEXT_READER diff --git a/neutron/objects/router.py b/neutron/objects/router.py index 2f1e314d93..5362a11c9b 100644 --- a/neutron/objects/router.py +++ b/neutron/objects/router.py @@ -163,6 +163,15 @@ class RouterPort(base.NeutronDbObject): query = query.distinct() return [r[0] for r in query] + @classmethod + @db_api.CONTEXT_READER + def get_gw_port_ids_by_router_id(cls, context, router_id): + query = context.session.query(l3.RouterPort) + query = query.filter( + l3.RouterPort.router_id == router_id, + l3.RouterPort.port_type == n_const.DEVICE_OWNER_ROUTER_GW) + return [rp.port_id for rp in query] + @base.NeutronObjectRegistry.register class DVRMacAddress(base.NeutronDbObject): @@ -411,8 +420,12 @@ class FloatingIP(base.NeutronDbObject): # Filter out on router_ids query = query.filter(l3.FloatingIP.router_id.in_(router_ids)) - # Remove duplicate rows based on FIP IDs - query = query.group_by(l3.FloatingIP.id) + # Remove duplicate rows based on FIP IDs and the subnet pool address + # scope. Only one subnet pool (per IP version, 4 in this case) can + # be assigned to a subnet. The subnet pool address scope for a FIP is + # unique. + query = query.group_by(l3.FloatingIP.id, + models_v2.SubnetPool.address_scope_id) for row in query: yield (cls._load_object(context, row[0]), row[1]) diff --git a/neutron/opts.py b/neutron/opts.py index b6117c9cc7..528126e71e 100644 --- a/neutron/opts.py +++ b/neutron/opts.py @@ -355,7 +355,10 @@ def list_ovs_opts(): ('dhcp', itertools.chain( neutron.conf.plugins.ml2.drivers.ovs_conf.dhcp_opts, - neutron.conf.agent.common.DHCP_PROTOCOL_OPTS)) + neutron.conf.agent.common.DHCP_PROTOCOL_OPTS)), + ('metadata', + itertools.chain( + meta_conf.METADATA_PROXY_HANDLER_OPTS)) ] diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_agent_extension_api.py b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_agent_extension_api.py index c6ec265a0b..aa4c3f4724 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_agent_extension_api.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_agent_extension_api.py @@ -41,12 +41,18 @@ class OVSAgentExtensionAPI(object): ''' def __init__(self, int_br, tun_br, phys_brs=None, - plugin_rpc=None): + plugin_rpc=None, + phys_ofports=None, + bridge_mappings=None): super(OVSAgentExtensionAPI, self).__init__() self.br_int = int_br self.br_tun = tun_br self.br_phys = phys_brs or {} self.plugin_rpc = plugin_rpc + # OVS agent extensions use this map to get physical device ofport. + self.phys_ofports = phys_ofports or {} + # OVS agent extensions use this map to get ovs bridge. + self.bridge_mappings = bridge_mappings or {} def request_int_br(self): """Allows extensions to request an integration bridge to use for @@ -74,3 +80,12 @@ class OVSAgentExtensionAPI(object): """ for phy_br in self.br_phys.values(): yield OVSCookieBridge(phy_br) + + def request_physical_br(self, name): + """Allows extensions to request one physical bridge to use for + extension specific flows. + """ + if not self.br_phys.get(name): + return None + + return OVSCookieBridge(self.br_phys.get(name)) 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 d6d45fe3f7..6f4407d441 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py @@ -312,10 +312,14 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin, self.ancillary_brs = self.setup_ancillary_bridges( ovs_conf.integration_bridge, ovs_conf.tunnel_bridge) - agent_api = ovs_ext_api.OVSAgentExtensionAPI(self.int_br, - self.tun_br, - self.phys_brs, - self.plugin_rpc) + agent_api = ovs_ext_api.OVSAgentExtensionAPI( + self.int_br, + self.tun_br, + self.phys_brs, + self.plugin_rpc, + phys_ofports=self.phys_ofports, + bridge_mappings=self.bridge_mappings) + self.ext_manager.initialize( self.connection, ovs_const.EXTENSION_DRIVER_TYPE, agent_api) @@ -1283,7 +1287,8 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin, # Otherwise, these flows will be cleaned as stale due to the # different cookie id. We also set refresh_tunnels if the agent # has not received a notification and is missing tunnels. - refresh_tunnels = (self.iter_num == 0) or tunnels_missing + refresh_tunnels = ((self.iter_num == 0) or tunnels_missing or + self.ovs_restarted) devices_set = self.plugin_rpc.update_device_list( self.context, devices_up, devices_down, self.agent_id, self.conf.host, refresh_tunnels=refresh_tunnels) @@ -2528,7 +2533,7 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin, LOG.info("Cleaning stale %s flows", self.tun_br.br_name) self.tun_br.cleanup_flows() - def process_port_info(self, start, polling_manager, sync, ovs_restarted, + def process_port_info(self, start, polling_manager, sync, ports, ancillary_ports, updated_ports_copy, consecutive_resyncs, ports_not_ready_yet, failed_devices, failed_ancillary_devices): @@ -2559,7 +2564,7 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin, # calling polling_manager.get_events() since # the agent might miss some event (for example a port # deletion) - reg_ports = (set() if ovs_restarted else ports) + reg_ports = (set() if self.ovs_restarted else ports) port_info = self.scan_ports(reg_ports, sync, updated_ports_copy) # Treat ancillary devices if they exist @@ -2682,6 +2687,10 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin, polling_manager.start() def rpc_loop(self, polling_manager): + # Everytime enter this loop this should always be set False again, + # in case of any break (or exception) after the value be set + # to True. + self.ovs_restarted = False idl_monitor = self.ovs.ovsdb.idl_monitor sync = False ports = set() @@ -2689,7 +2698,6 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin, activated_bindings_copy = set() ancillary_ports = set() tunnel_sync = True - ovs_restarted = False consecutive_resyncs = 0 need_clean_stale_flow = True ports_not_ready_yet = set() @@ -2736,7 +2744,7 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin, except Exception: LOG.exception("Error while configuring tunnel endpoints") tunnel_sync = True - ovs_restarted |= (self.ovs_status == ovs_const.OVS_RESTARTED) + self.ovs_restarted |= (self.ovs_status == ovs_const.OVS_RESTARTED) devices_need_retry = (any(failed_devices.values()) or any(failed_ancillary_devices.values()) or ports_not_ready_yet) @@ -2767,7 +2775,7 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin, self.activated_bindings = set() (port_info, ancillary_port_info, consecutive_resyncs, ports_not_ready_yet) = (self.process_port_info( - start, polling_manager, sync, ovs_restarted, + start, polling_manager, sync, ports, ancillary_ports, updated_ports_copy, consecutive_resyncs, ports_not_ready_yet, failed_devices, failed_ancillary_devices)) @@ -2789,11 +2797,11 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin, # on Neutron server if (self._port_info_has_changes(port_info) or self.sg_agent.firewall_refresh_needed() or - ovs_restarted): + self.ovs_restarted): LOG.debug("Starting to process devices in:%s", port_info) provisioning_needed = ( - ovs_restarted or bridges_recreated) + self.ovs_restarted or bridges_recreated) failed_devices = self.process_network_ports( port_info, provisioning_needed) LOG.info("Agent rpc_loop - iteration:%(iter_num)d - " @@ -2827,9 +2835,6 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin, self.update_retries_map_and_remove_devs_not_to_retry( failed_devices, failed_ancillary_devices, failed_devices_retries_map)) - # Keep this flag in the last line of "try" block, - # so we can sure that no other Exception occurred. - ovs_restarted = False self._dispose_local_vlan_hints() except Exception: LOG.exception("Error while processing VIF ports") @@ -2837,6 +2842,7 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin, self.updated_ports |= updated_ports_copy self.activated_bindings |= activated_bindings_copy sync = True + self.ovs_restarted = False port_stats = self.get_port_stats(port_info, ancillary_port_info) self.loop_count_and_wait(start, port_stats) diff --git a/neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py b/neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py index ef16d06227..c92e942161 100644 --- a/neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py +++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py @@ -214,6 +214,10 @@ class OVNMechanismDriver(api.MechanismDriver): portbindings.CAP_PORT_FILTER: self.sg_enabled, portbindings.VIF_DETAILS_CONNECTIVITY: self.connectivity, }, + portbindings.VIF_TYPE_AGILIO_OVS: { + portbindings.CAP_PORT_FILTER: self.sg_enabled, + portbindings.VIF_DETAILS_CONNECTIVITY: self.connectivity, + }, portbindings.VIF_TYPE_VHOST_USER: { portbindings.CAP_PORT_FILTER: False, portbindings.VHOST_USER_MODE: @@ -265,9 +269,6 @@ class OVNMechanismDriver(api.MechanismDriver): registry.subscribe(self._create_security_group, resources.SECURITY_GROUP, events.AFTER_CREATE) - registry.subscribe(self._delete_security_group_precommit, - resources.SECURITY_GROUP, - events.PRECOMMIT_DELETE) registry.subscribe(self._delete_security_group, resources.SECURITY_GROUP, events.AFTER_DELETE) @@ -280,6 +281,9 @@ class OVNMechanismDriver(api.MechanismDriver): registry.subscribe(self._process_sg_rule_notification, resources.SECURITY_GROUP_RULE, events.BEFORE_DELETE) + registry.subscribe(self._process_sg_rule_after_del_notification, + resources.SECURITY_GROUP_RULE, + events.AFTER_DELETE) def _clean_hash_ring(self, *args, **kwargs): admin_context = n_context.get_admin_context() @@ -396,14 +400,6 @@ class OVNMechanismDriver(api.MechanismDriver): self._ovn_client.create_security_group(context, security_group) - def _delete_security_group_precommit(self, resource, event, trigger, - payload): - context = n_context.get_admin_context() - security_group_id = payload.resource_id - for sg_rule in self._plugin.get_security_group_rules( - context, filters={'remote_group_id': [security_group_id]}): - self._ovn_client.delete_security_group_rule(context, sg_rule) - def _delete_security_group(self, resource, event, trigger, payload): context = payload.context security_group_id = payload.resource_id @@ -461,6 +457,12 @@ class OVNMechanismDriver(api.MechanismDriver): context, sg_rule) + def _process_sg_rule_after_del_notification( + self, resource, event, trigger, payload): + context = payload.context + sg_rule = payload.metadata['rule'] + self._ovn_client.delete_security_group_rule(context, sg_rule) + def _sg_has_rules_with_same_normalized_cidr(self, sg_rule): compare_keys = [ 'ethertype', 'direction', 'protocol', @@ -1025,6 +1027,17 @@ class OVNMechanismDriver(api.MechanismDriver): vif_details = dict(self.vif_details[vif_type]) vif_details[portbindings.VHOST_USER_SOCKET] = ( vhost_user_socket) + elif (vnic_type == portbindings.VNIC_VIRTIO_FORWARDER): + vhost_user_socket = ovn_utils.ovn_vhu_sockpath( + ovn_conf.get_ovn_vhost_sock_dir(), port['id']) + vif_type = portbindings.VIF_TYPE_AGILIO_OVS + port[portbindings.VIF_DETAILS].update({ + portbindings.VHOST_USER_SOCKET: vhost_user_socket}) + vif_details = dict(self.vif_details[vif_type]) + vif_details[portbindings.VHOST_USER_SOCKET] = ( + vhost_user_socket) + vif_details[portbindings.VHOST_USER_MODE] = ( + portbindings.VHOST_USER_MODE_CLIENT) else: vif_type = portbindings.VIF_TYPE_OVS vif_details = self.vif_details[vif_type] diff --git a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/commands.py b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/commands.py index 10cdc3f031..b3a7bdca80 100644 --- a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/commands.py +++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/commands.py @@ -836,19 +836,8 @@ class DeleteLRouterExtGwCommand(command.BaseCommand): lrouter.delvalue('nat', nat) nat.delete() - lrouter_ext_ids = getattr(lrouter, 'external_ids', {}) - gw_port_id = lrouter_ext_ids.get(ovn_const.OVN_GW_PORT_EXT_ID_KEY) - if not gw_port_id: - return - - try: - lrouter_port = idlutils.row_by_value( - self.api.idl, 'Logical_Router_Port', 'name', - utils.ovn_lrouter_port_name(gw_port_id)) - except idlutils.RowNotFound: - return - - lrouter.delvalue('ports', lrouter_port) + for gw_port in self.api.get_lrouter_gw_ports(lrouter.name): + lrouter.delvalue('ports', gw_port) class SetLSwitchPortToVirtualTypeCommand(command.BaseCommand): diff --git a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py index 45da53c93d..1b663c5a64 100644 --- a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py +++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/qos.py @@ -425,13 +425,6 @@ class OVNClientQosExtension(object): def disassociate_floatingip(self, txn, floatingip): self.delete_floatingip(txn, floatingip) - def _delete_gateway_ip_qos_rules(self, txn, router_id, network_id): - if network_id: - lswitch_name = utils.ovn_name(network_id) - txn.add(self.nb_idl.qos_del_ext_ids( - lswitch_name, - {ovn_const.OVN_ROUTER_ID_EXT_ID_KEY: router_id})) - def create_router(self, txn, router): self.update_router(txn, router) @@ -465,10 +458,6 @@ class OVNClientQosExtension(object): # Delete, if exists, the QoS rule in this direction. txn.add(self.nb_idl.qos_del(**ovn_rule, if_exists=True)) - def delete_router(self, txn, router): - self._delete_gateway_ip_qos_rules(txn, router['id'], - router['gw_network_id']) - def update_policy(self, context, policy): updated_port_ids = set([]) updated_fip_ids = set([]) diff --git a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/impl_idl_ovn.py b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/impl_idl_ovn.py index be5e7db367..8c74661c15 100644 --- a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/impl_idl_ovn.py +++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/impl_idl_ovn.py @@ -785,6 +785,22 @@ class OvsdbNbOvnIdl(nb_impl_idl.OvnNbApiIdlImpl, Backend): result = lrp.execute(check_error=True) return result[0] if result else None + def get_lrouter_gw_ports(self, lrouter_name): + lr = self.get_lrouter(lrouter_name) + gw_ports = [] + for lrp in getattr(lr, 'ports', []): + lrp_ext_ids = getattr(lrp, 'external_ids', {}) + if (ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY not in lrp_ext_ids or + utils.ovn_name(lrp_ext_ids[ + ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY]) != lr.name): + continue + lrp_ha_cfg = (getattr(lrp, 'gateway_chassis', None) or + getattr(lrp, 'options', {}).get( + ovn_const.OVN_GATEWAY_CHASSIS_KEY)) + if lrp_ha_cfg: + gw_ports.append(lrp) + return gw_ports + def delete_lrouter_ext_gw(self, lrouter_name, if_exists=True): return cmd.DeleteLRouterExtGwCommand(self, lrouter_name, if_exists) diff --git a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/maintenance.py b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/maintenance.py index 29a3848b28..7f4b15c0ee 100644 --- a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/maintenance.py +++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/maintenance.py @@ -41,6 +41,7 @@ from neutron.db import ovn_revision_numbers_db as revision_numbers_db from neutron.objects import ports as ports_obj from neutron.objects import router as router_obj from neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb import ovn_db_sync +from neutron.services.logapi.drivers.ovn import driver as log_driver CONF = cfg.CONF @@ -650,6 +651,36 @@ class DBInconsistenciesPeriodics(SchemaAwarePeriodicsBase): raise periodics.NeverAgain() + # A static spacing value is used here, but this method will only run + # once per lock due to the use of periodics.NeverAgain(). + @periodics.periodic(spacing=600, run_immediately=True) + def check_localnet_port_has_learn_fdb(self): + if not self.has_lock: + return + + ports = self._nb_idl.db_find_rows( + "Logical_Switch_Port", ("type", "=", ovn_const.LSP_TYPE_LOCALNET) + ).execute(check_error=True) + + with self._nb_idl.transaction(check_error=True) as txn: + for port in ports: + if ovn_conf.is_learn_fdb_enabled(): + fdb_opt = port.options.get( + ovn_const.LSP_OPTIONS_LOCALNET_LEARN_FDB) + if not fdb_opt or fdb_opt == 'false': + txn.add(self._nb_idl.db_set( + 'Logical_Switch_Port', port.name, + ('options', + {ovn_const.LSP_OPTIONS_LOCALNET_LEARN_FDB: 'true'} + ))) + elif port.options.get( + ovn_const.LSP_OPTIONS_LOCALNET_LEARN_FDB) == 'true': + txn.add(self._nb_idl.db_set( + 'Logical_Switch_Port', port.name, + ('options', + {ovn_const.LSP_OPTIONS_LOCALNET_LEARN_FDB: 'false'}))) + raise periodics.NeverAgain() + # TODO(lucasagomes): Remove this in the Z cycle # A static spacing value is used here, but this method will only run # once per lock due to the use of periodics.NeverAgain(). @@ -775,30 +806,31 @@ class DBInconsistenciesPeriodics(SchemaAwarePeriodicsBase): txn.add(cmd) raise periodics.NeverAgain() - # TODO(ralonsoh): Remove this in the Z+3 cycle. This method adds the - # "external_ids:OVN_GW_NETWORK_EXT_ID_KEY" to each router that has - # a gateway (that means, that has "external_ids:OVN_GW_PORT_EXT_ID_KEY"). + # TODO(fnordahl): Remove this in the B+3 cycle. This method removes the + # now redundant "external_ids:OVN_GW_NETWORK_EXT_ID_KEY" and + # "external_ids:OVN_GW_PORT_EXT_ID_KEY" from to each router. # A static spacing value is used here, but this method will only run # once per lock due to the use of periodics.NeverAgain(). @periodics.periodic(spacing=600, run_immediately=True) - def update_logical_router_with_gateway_network_id(self): - """Update all OVN logical router registers with the GW network ID""" + def remove_gw_ext_ids_from_logical_router(self): + """Remove `gw_port_id` and `gw_network_id` external_ids from LRs""" if not self.has_lock: return cmds = [] - context = n_context.get_admin_context() for lr in self._nb_idl.lr_list().execute(check_error=True): - gw_port = lr.external_ids.get(ovn_const.OVN_GW_PORT_EXT_ID_KEY) - gw_net = lr.external_ids.get(ovn_const.OVN_GW_NETWORK_EXT_ID_KEY) - if not gw_port or (gw_port and gw_net): - # This router does not have a gateway network assigned yet or - # it has a gateway port and its corresponding network. + if (ovn_const.OVN_GW_PORT_EXT_ID_KEY not in lr.external_ids and + ovn_const.OVN_GW_NETWORK_EXT_ID_KEY not in + lr.external_ids): + # This router have none of the deprecated external_ids. continue - port = self._ovn_client._plugin.get_port(context, gw_port) - external_ids = { - ovn_const.OVN_GW_NETWORK_EXT_ID_KEY: port['network_id']} + external_ids = lr.external_ids.copy() + for k in (ovn_const.OVN_GW_PORT_EXT_ID_KEY, + ovn_const.OVN_GW_NETWORK_EXT_ID_KEY): + if k in external_ids: + del(external_ids[k]) + cmds.append(self._nb_idl.db_set( 'Logical_Router', lr.uuid, ('external_ids', external_ids))) @@ -985,6 +1017,24 @@ class DBInconsistenciesPeriodics(SchemaAwarePeriodicsBase): raise periodics.NeverAgain() + @periodics.periodic(spacing=600, run_immediately=True) + def check_fair_meter_consistency(self): + """Update the logging meter after neutron-server reload + + When we change the rate and burst limit we need to update the fair + meter band to apply the new values. This is called from the ML2/OVN + driver after the OVN NB idl is loaded + + """ + if not self.has_lock: + return + if log_driver.OVNDriver.network_logging_supported(self._nb_idl): + meter_name = ( + cfg.CONF.network_log.local_output_log_base or "acl_log_meter") + self._ovn_client.create_ovn_fair_meter(meter_name, + from_reload=True) + raise periodics.NeverAgain() + class HashRingHealthCheckPeriodics(object): diff --git a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py index f5607e2849..9a40a568f2 100644 --- a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py +++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py @@ -31,6 +31,7 @@ from neutron_lib.exceptions import l3 as l3_exc from neutron_lib.plugins import constants as plugin_constants from neutron_lib.plugins import directory from neutron_lib.plugins import utils as p_utils +from neutron_lib.services.logapi import constants as log_const from neutron_lib.utils import helpers from neutron_lib.utils import net as n_net from oslo_config import cfg @@ -1329,20 +1330,17 @@ class OVNClient(object): 'device_owner': [const.DEVICE_OWNER_ROUTER_GW], 'device_id': [router_id]}) - def _get_router_ports(self, context, router_id, get_gw_port=False): + def _get_router_ports(self, context, router_id): # _get_router() will raise a RouterNotFound error if there's no router # with the router_id router_db = self._l3_plugin._get_router(context, router_id) - if get_gw_port: - return [p.port for p in router_db.attached_ports] - else: - # When the existing deployment is migrated to OVN - # we may need to consider other port types - DVR_INTERFACE/HA_INTF. - return [p.port for p in router_db.attached_ports - if p.port_type in [const.DEVICE_OWNER_ROUTER_INTF, - const.DEVICE_OWNER_DVR_INTERFACE, - const.DEVICE_OWNER_HA_REPLICATED_INT, - const.DEVICE_OWNER_ROUTER_HA_INTF]] + # When the existing deployment is migrated to OVN + # we may need to consider other port types - DVR_INTERFACE/HA_INTF. + return [p.port for p in router_db.attached_ports + if p.port_type in [const.DEVICE_OWNER_ROUTER_INTF, + const.DEVICE_OWNER_DVR_INTERFACE, + const.DEVICE_OWNER_HA_REPLICATED_INT, + const.DEVICE_OWNER_ROUTER_HA_INTF]] def _get_v4_network_for_router_port(self, context, port): cidr = None @@ -1366,18 +1364,13 @@ class OVNClient(object): return networks def _gen_router_ext_ids(self, router): - gw_net_id = (router.get('external_gateway_info') or - {}).get('network_id') or '' return { ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: router.get('name', 'no_router_name'), - ovn_const.OVN_GW_PORT_EXT_ID_KEY: - router.get('gw_port_id') or '', ovn_const.OVN_REV_NUM_EXT_ID_KEY: str(utils.get_revision_number( router, ovn_const.TYPE_ROUTERS)), ovn_const.OVN_AZ_HINTS_EXT_ID_KEY: ','.join(common_utils.get_az_hints(router)), - ovn_const.OVN_GW_NETWORK_EXT_ID_KEY: gw_net_id, } def create_router(self, context, router, add_external_gateway=True): @@ -1498,13 +1491,8 @@ class OVNClient(object): def delete_router(self, context, router_id): """Delete a logical router.""" lrouter_name = utils.ovn_name(router_id) - ovn_router = self._nb_idl.get_lrouter(lrouter_name) - gw_network_id = ovn_router.external_ids.get( - ovn_const.OVN_GW_NETWORK_EXT_ID_KEY) if ovn_router else None - router_dict = {'id': router_id, 'gw_network_id': gw_network_id} with self._nb_idl.transaction(check_error=True) as txn: txn.add(self._nb_idl.delete_lrouter(lrouter_name)) - self._qos_driver.delete_router(txn, router_dict) db_rev.delete_revision(context, router_id, ovn_const.TYPE_ROUTERS) def get_candidates_for_scheduling(self, physnet, cms=None, @@ -1914,9 +1902,12 @@ class OVNClient(object): def create_provnet_port(self, network_id, segment, txn=None): tag = segment.get(segment_def.SEGMENTATION_ID, []) physnet = segment.get(segment_def.PHYSICAL_NETWORK) + fdb_enabled = ('true' if ovn_conf.is_learn_fdb_enabled() + else 'false') options = {'network_name': physnet, ovn_const.LSP_OPTIONS_MCAST_FLOOD_REPORTS: 'true', - ovn_const.LSP_OPTIONS_MCAST_FLOOD: 'false'} + ovn_const.LSP_OPTIONS_MCAST_FLOOD: 'false', + ovn_const.LSP_OPTIONS_LOCALNET_LEARN_FDB: fdb_enabled} cmd = self._nb_idl.create_lswitch_port( lport_name=utils.ovn_provnet_port_name(segment['id']), lswitch_name=utils.ovn_name(network_id), @@ -2336,7 +2327,7 @@ class OVNClient(object): mport_updated = False if subnet['ip_version'] == const.IP_VERSION_4: mport_updated = self.update_metadata_port( - context, network['id'], subnet=subnet) + context, network, subnet=subnet) if subnet['ip_version'] == const.IP_VERSION_6 or not mport_updated: # NOTE(ralonsoh): if IPv4 but the metadata port has not been # updated, the DHPC options register has not been created. @@ -2356,7 +2347,7 @@ class OVNClient(object): subnet['id'])['subnet'] if subnet['enable_dhcp'] or ovn_subnet: - self.update_metadata_port(context, network['id'], subnet=subnet) + self.update_metadata_port(context, network, subnet=subnet) check_rev_cmd = self._nb_idl.check_revision_number( subnet['id'], subnet, ovn_const.TYPE_SUBNETS) @@ -2452,8 +2443,9 @@ class OVNClient(object): if not ovn_conf.is_ovn_metadata_enabled(): return - if self._find_metadata_port(context, network['id']): - return + metadata_port = self._find_metadata_port(context, network['id']) + if metadata_port: + return metadata_port # Create a neutron port for DHCP/metadata services filters = {'network_id': [network['id']]} @@ -2468,16 +2460,19 @@ class OVNClient(object): } } # TODO(boden): rehome create_port into neutron-lib - p_utils.create_port(self._plugin, context, port) + return p_utils.create_port(self._plugin, context, port) - def update_metadata_port(self, context, network_id, subnet=None): + def update_metadata_port(self, context, network, subnet=None): """Update metadata port. This function will allocate an IP address for the metadata port of the given network in all its IPv4 subnets or the given subnet. Returns "True" if the metadata port has been updated and "False" if OVN - metadata is disabled or the metadata port does not exist. + metadata is disabled or the metadata port does not exist or + cannot be created. """ + network_id = network['id'] + def update_metadata_port_fixed_ips(metadata_port, add_subnet_ids, del_subnet_ids): wanted_fixed_ips = [ @@ -2496,11 +2491,11 @@ class OVNClient(object): if not ovn_conf.is_ovn_metadata_enabled(): return False - # Retrieve the metadata port of this network - metadata_port = self._find_metadata_port(context, network_id) + # Retrieve or create the metadata port of this network + metadata_port = self.create_metadata_port(context, network) if not metadata_port: - LOG.error("Metadata port couldn't be found for network %s", - network_id) + LOG.error("Metadata port could not be found or created " + "for network %s", network_id) return False port_subnet_ids = set(ip['subnet_id'] for ip in @@ -2653,3 +2648,54 @@ class OVNClient(object): if ls_dns_record.records.get(ptr_record): txn.add(self._nb_idl.dns_remove_record( ls_dns_record.uuid, ptr_record, if_exists=True)) + + def create_ovn_fair_meter(self, meter_name, from_reload=False, txn=None): + """Create row in Meter table with fair attribute set to True. + + Create a row in OVN's NB Meter table based on well-known name. This + method uses the network_log configuration to specify the attributes + of the meter. Current implementation needs only one 'fair' meter row + which is then referred by multiple ACL rows. + + :param meter_name: ovn northbound meter name. + :param from_reload: whether we update the meter values or create them. + :txn: ovn northbound idl transaction. + + """ + meter = self._nb_idl.db_find_rows( + "Meter", ("name", "=", meter_name)).execute(check_error=True) + # The meter is created when a log object is created, not by default. + # This condition avoids creating the meter if it wasn't there already + commands = [] + if from_reload and not meter: + return + if meter: + meter = meter[0] + meter_band = self._nb_idl.lookup("Meter_Band", + meter.bands[0].uuid, default=None) + if meter_band: + if all((meter.unit == "pktps", + meter.fair[0], + meter_band.rate == cfg.CONF.network_log.rate_limit, + meter_band.burst_size == + cfg.CONF.network_log.burst_limit)): + # Meter (and its meter-band) unchanged: noop. + return + # Re-create meter (and its meter-band) with the new attributes. + # This is supposed to happen only if configuration changed, so + # doing updates is an overkill: better to leverage the ovsdbapp + # library to avoid the complexity. + LOG.info("Deleting outdated log fair meter %s", meter_name) + commands.append(self._nb_idl.meter_del(meter.uuid)) + # Create meter + LOG.info("Creating network log fair meter %s", meter_name) + commands.append(self._nb_idl.meter_add( + name=meter_name, + unit="pktps", + rate=cfg.CONF.network_log.rate_limit, + fair=True, + burst_size=cfg.CONF.network_log.burst_limit, + may_exist=False, + external_ids={ovn_const.OVN_DEVICE_OWNER_EXT_ID_KEY: + log_const.LOGGING_PLUGIN})) + self._transaction(commands, txn=txn) diff --git a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_db_sync.py b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_db_sync.py index 0a307f78ee..f53bc8423b 100644 --- a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_db_sync.py +++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_db_sync.py @@ -960,7 +960,7 @@ class OvnNbSynchronizer(OvnDbSynchronizer): try: # Make sure that this port has an IP address in all the # subnets - self._ovn_client.update_metadata_port(ctx, net['id']) + self._ovn_client.update_metadata_port(ctx, net) except n_exc.IpAddressGenerationFailure: LOG.error('Could not allocate IP addresses for ' 'metadata port in network %s', net['id']) diff --git a/neutron/plugins/ml2/extensions/port_hints.py b/neutron/plugins/ml2/extensions/port_hints.py new file mode 100644 index 0000000000..1e4ba654f4 --- /dev/null +++ b/neutron/plugins/ml2/extensions/port_hints.py @@ -0,0 +1,45 @@ +# Copyright 2023 Ericsson Software Technology +# +# 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. + +from neutron_lib.api.definitions import port_hints as phints_def +from neutron_lib.plugins.ml2 import api +from oslo_log import log as logging + +from neutron.db import port_hints_db + + +LOG = logging.getLogger(__name__) + + +class PortHintsExtensionDriver( + api.ExtensionDriver, port_hints_db.PortHintsMixin): + + _supported_extension_alias = phints_def.ALIAS + + def initialize(self): + LOG.info('PortHintsExtensionDriver initialization complete') + + @property + def extension_alias(self): + return self._supported_extension_alias + + def process_create_port(self, context, data, result): + self._process_create_port(context, data, result) + + def process_update_port(self, context, data, result): + if phints_def.HINTS in data: + self._process_update_port(context, data, result) + + def extend_port_dict(self, session, port_db, result): + self._extend_port_dict(port_db, result) diff --git a/neutron/policy.py b/neutron/policy.py index dca079b3c9..e4f0b093bd 100644 --- a/neutron/policy.py +++ b/neutron/policy.py @@ -51,12 +51,15 @@ _RESOURCE_FOREIGN_KEYS = { 'security_groups': 'security_group_id' } - -# TODO(gmann): Remove setting the default value of config policy_file -# once oslo_policy change the default value to 'policy.yaml'. -# https://github.com/openstack/oslo.policy/blob/a626ad12fe5a3abd49d70e3e5b95589d279ab578/oslo_policy/opts.py#L49 +# TODO(slaweq): Remove overriding the default value of config options +# 'policy_file', 'enforce_scope', and 'enforce_new_defaults' once +# oslo_policy change their default value to what is overridden here. DEFAULT_POLICY_FILE = 'policy.yaml' -opts.set_defaults(cfg.CONF, DEFAULT_POLICY_FILE) +opts.set_defaults( + cfg.CONF, + DEFAULT_POLICY_FILE, + enforce_scope=True, + enforce_new_defaults=True) def reset(): diff --git a/neutron/services/logapi/drivers/ovn/driver.py b/neutron/services/logapi/drivers/ovn/driver.py index eeca2f18d3..8a4c8d2de6 100644 --- a/neutron/services/logapi/drivers/ovn/driver.py +++ b/neutron/services/logapi/drivers/ovn/driver.py @@ -90,53 +90,13 @@ class OVNDriver(base.DriverBase): return [self._log_dict_to_obj(lo) for lo in log_objs] @property + def _ovn_client(self): + return self.plugin_driver._ovn_client + + @property def ovn_nb(self): return self.plugin_driver.nb_ovn - def _create_ovn_fair_meter(self, ovn_txn): - """Create row in Meter table with fair attribute set to True. - - Create a row in OVN's NB Meter table based on well-known name. This - method uses the network_log configuration to specify the attributes - of the meter. Current implementation needs only one 'fair' meter row - which is then referred by multiple ACL rows. - - :param ovn_txn: ovn northbound idl transaction. - - """ - meter = self.ovn_nb.db_find_rows( - "Meter", ("name", "=", self.meter_name)).execute(check_error=True) - if meter: - meter = meter[0] - try: - meter_band = self.ovn_nb.lookup("Meter_Band", - meter.bands[0].uuid) - if all((meter.unit == "pktps", - meter.fair[0], - meter_band.rate == cfg.CONF.network_log.rate_limit, - meter_band.burst_size == - cfg.CONF.network_log.burst_limit)): - # Meter (and its meter-band) unchanged: noop. - return - except idlutils.RowNotFound: - pass - # Re-create meter (and its meter-band) with the new attributes. - # This is supposed to happen only if configuration changed, so - # doing updates is an overkill: better to leverage the ovsdbapp - # library to avoid the complexity. - ovn_txn.add(self.ovn_nb.meter_del(meter.uuid)) - # Create meter - LOG.info("Creating network log fair meter %s", self.meter_name) - ovn_txn.add(self.ovn_nb.meter_add( - name=self.meter_name, - unit="pktps", - rate=cfg.CONF.network_log.rate_limit, - fair=True, - burst_size=cfg.CONF.network_log.burst_limit, - may_exist=False, - external_ids={ovn_const.OVN_DEVICE_OWNER_EXT_ID_KEY: - log_const.LOGGING_PLUGIN})) - @staticmethod def _acl_actions_enabled(log_obj): if not log_obj.enabled: @@ -303,7 +263,8 @@ class OVNDriver(base.DriverBase): pgs = self._pgs_from_log_obj(context, log_obj) actions_enabled = self._acl_actions_enabled(log_obj) with self.ovn_nb.transaction(check_error=True) as ovn_txn: - self._create_ovn_fair_meter(ovn_txn) + self._ovn_client.create_ovn_fair_meter(self.meter_name, + txn=ovn_txn) self._set_acls_log(pgs, ovn_txn, actions_enabled, utils.ovn_name(log_obj.id)) diff --git a/neutron/services/loki/loki_plugin.py b/neutron/services/loki/loki_plugin.py index 491f914b86..9d496f523e 100644 --- a/neutron/services/loki/loki_plugin.py +++ b/neutron/services/loki/loki_plugin.py @@ -34,11 +34,13 @@ class LokiPlugin(service_base.ServicePluginBase): def random_deadlock(self, session, flush_context, instances): if random.randrange(0, 51) > 49: # 1/50 probability + LOG.info("Loki has raised a DBDeadlock exception, instances %s", + instances) raise db_exc.DBDeadlock() def random_delay(self, session, instance): if random.randrange(0, 201) > 199: # 1/200 probability - LOG.debug("Loki has delayed loading of instance %s", instance) + LOG.info("Loki has delayed loading of instance %s", instance) time.sleep(1) def get_plugin_type(self): diff --git a/neutron/services/ovn_l3/plugin.py b/neutron/services/ovn_l3/plugin.py index 56a58d3f5e..7d370089a2 100644 --- a/neutron/services/ovn_l3/plugin.py +++ b/neutron/services/ovn_l3/plugin.py @@ -170,6 +170,7 @@ class OVNL3RouterPlugin(service_base.ServicePluginBase, def create_router_precommit(self, resource, event, trigger, payload): context = payload.context + context.session.flush() router_id = payload.resource_id router_db = payload.metadata['router_db'] diff --git a/neutron/services/qos/qos_plugin.py b/neutron/services/qos/qos_plugin.py index 776dae6da2..d4f5d5038e 100644 --- a/neutron/services/qos/qos_plugin.py +++ b/neutron/services/qos/qos_plugin.py @@ -323,7 +323,7 @@ class QoSPlugin(qos.QoSPluginBase): def _get_ports_with_policy(self, context, policy): networks_ids = policy.get_bound_networks() ports_with_net_policy = ports_object.Port.get_objects( - context, network_id=networks_ids) + context, network_id=networks_ids) if networks_ids else [] # Filter only this ports which don't have overwritten policy ports_with_net_policy = [ @@ -333,7 +333,7 @@ class QoSPlugin(qos.QoSPluginBase): ports_ids = policy.get_bound_ports() ports_with_policy = ports_object.Port.get_objects( - context, id=ports_ids) + context, id=ports_ids) if ports_ids else [] return list(set(ports_with_policy + ports_with_net_policy)) def _validate_create_port_callback(self, resource, event, trigger, diff --git a/neutron/services/tag/tag_plugin.py b/neutron/services/tag/tag_plugin.py index c44860034d..23f3cb9ed1 100644 --- a/neutron/services/tag/tag_plugin.py +++ b/neutron/services/tag/tag_plugin.py @@ -100,6 +100,7 @@ class TagPlugin(tagging.TagPluginBase): tag=tag).create() @log_helpers.log_method_call + @db_api.retry_if_session_inactive() def update_tag(self, context, resource, resource_id, tag): res = self._get_resource(context, resource, resource_id) if any(tag == tag_db.tag for tag_db in res.standard_attr.tags): @@ -111,12 +112,14 @@ class TagPlugin(tagging.TagPluginBase): pass @log_helpers.log_method_call + @db_api.retry_if_session_inactive() def delete_tags(self, context, resource, resource_id): res = self._get_resource(context, resource, resource_id) tag_obj.Tag.delete_objects(context, standard_attr_id=res.standard_attr_id) @log_helpers.log_method_call + @db_api.retry_if_session_inactive() def delete_tag(self, context, resource, resource_id, tag): res = self._get_resource(context, resource, resource_id) if not tag_obj.Tag.delete_objects( diff --git a/neutron/tests/base.py b/neutron/tests/base.py index 92782099f2..53bd380fc2 100644 --- a/neutron/tests/base.py +++ b/neutron/tests/base.py @@ -46,7 +46,6 @@ from oslotest import base from osprofiler import profiler from sqlalchemy import exc as sqlalchemy_exc import testtools -from testtools import content from neutron._i18n import _ from neutron.agent.linux import external_process @@ -68,8 +67,6 @@ ETCDIR = os.path.join(ROOTDIR, 'etc') SUDO_CMD = 'sudo -n' -TESTCASE_RETRIES = 3 - def etcdir(*p): return os.path.join(ETCDIR, *p) @@ -177,26 +174,10 @@ class AttributeDict(dict): def _catch_timeout(f): @functools.wraps(f) def func(self, *args, **kwargs): - for idx in range(1, TESTCASE_RETRIES + 1): - try: - return f(self, *args, **kwargs) - except eventlet.Timeout as e: - self.fail('Execution of this test timed out: %s' % e) - # NOTE(ralonsoh): exception catch added due to the constant - # occurrences of this exception during FT and UT execution. - # This is due to [1]. Once the sync decorators are removed or the - # privsep ones are decorated by those ones (swap decorator - # declarations) this catch can be remove. - # [1] https://review.opendev.org/#/c/631275/ - except fixtures.TimeoutException: - if idx < TESTCASE_RETRIES: - msg = ('"fixtures.TimeoutException" during test case ' - 'execution no %s; test case re-executed' % idx) - self.addDetail('DietTestCase', - content.text_content(msg)) - self._set_timeout() - else: - self.fail('Execution of this test timed out') + try: + return f(self, *args, **kwargs) + except eventlet.Timeout as e: + self.fail('Execution of this test timed out: %s' % e) return func @@ -553,6 +534,7 @@ class PluginFixture(fixtures.Fixture): self.core_plugin = core_plugin def _setUp(self): + config.register_common_config_options() # Do not load default service plugins in the testing framework # as all the mocking involved can cause havoc. self.default_svc_plugins_p = mock.patch( diff --git a/neutron/tests/common/net_helpers.py b/neutron/tests/common/net_helpers.py index 89f9042db9..ce8926f4bb 100644 --- a/neutron/tests/common/net_helpers.py +++ b/neutron/tests/common/net_helpers.py @@ -24,6 +24,7 @@ import shlex import signal import subprocess import time +from unittest import mock import fixtures import netaddr @@ -880,20 +881,19 @@ class OVSPortFixture(PortFixture): interface_config = cfg.ConfigOpts() config.register_interface_opts(interface_config) ovs_interface = interface.OVSInterfaceDriver(interface_config) - ovs_interface.plug_new( - None, - self.port_id, - port_name, - self.mac, - bridge=self.bridge.br_name, - namespace=self.namespace) - # NOTE(mangelajo): for OVS implementations remove the DEAD VLAN tag - # on ports that we intend to use as fake vm interfaces, they - # need to be flat. This is related to lp#1767422 - self.bridge.clear_db_attribute("Port", port_name, "tag") - # Clear vlan_mode that is added for each new port. lp#1930414 - self.bridge.clear_db_attribute("Port", port_name, "vlan_mode") - self.bridge.clear_db_attribute("Port", port_name, "trunks") + # NOTE(slaweq): for OVS implementation normally there would be DEAD + # VLAN tag set for port and we would need to remove it here as it is + # needed during the tests. But to avoid setting and removing tag, we + # can simply mock _set_port_dead method so port will not be tagged with + # DEAD_VLAN tag initially + with mock.patch.object(ovs_lib.OVSBridge, '_set_port_dead'): + ovs_interface.plug_new( + None, + self.port_id, + port_name, + self.mac, + bridge=self.bridge.br_name, + namespace=self.namespace) self.addCleanup(self.bridge.delete_port, port_name) self.port = ip_lib.IPDevice(port_name, self.namespace) diff --git a/neutron/tests/fullstack/test_dhcp_agent.py b/neutron/tests/fullstack/test_dhcp_agent.py index e6c05b6bca..6d19a30736 100644 --- a/neutron/tests/fullstack/test_dhcp_agent.py +++ b/neutron/tests/fullstack/test_dhcp_agent.py @@ -19,7 +19,6 @@ from oslo_utils import uuidutils from neutron.agent.linux import ip_lib from neutron.common import utils as common_utils -from neutron.tests import base as test_base from neutron.tests.fullstack.agents import dhcp_agent from neutron.tests.fullstack import base from neutron.tests.fullstack.resources import environment @@ -185,7 +184,6 @@ class TestDhcpAgentHA(BaseDhcpAgentTest): # check if new vm will get IP from new DHCP agent self._spawn_vm() - @test_base.unstable_test('bug 2000150') def test_multiple_agents_for_network(self): network_dhcp_agents = self.client.list_dhcp_agent_hosting_networks( self.network['id'])['agents'] diff --git a/neutron/tests/functional/agent/linux/test_keepalived.py b/neutron/tests/functional/agent/linux/test_keepalived.py index aa36cd250f..699dc25213 100644 --- a/neutron/tests/functional/agent/linux/test_keepalived.py +++ b/neutron/tests/functional/agent/linux/test_keepalived.py @@ -13,7 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import signal from oslo_config import cfg @@ -27,6 +26,7 @@ from neutron.tests.common import net_helpers from neutron.tests.functional.agent.linux import helpers from neutron.tests.functional import base from neutron.tests.unit.agent.linux import test_keepalived +from neutron_lib.exceptions import ProcessExecutionError class KeepalivedManagerTestCase(base.BaseSudoTestCase, @@ -51,12 +51,17 @@ class KeepalivedManagerTestCase(base.BaseSudoTestCase, self.addCleanup(self._stop_keepalived_manager) def _stop_keepalived_manager(self): - self.manager.disable() try: - common_utils.wait_until_true( - lambda: not self.manager.get_process().active, timeout=5) - except common_utils.WaitTimeout: - self.manager.get_process().disable(sig=signal.SIGKILL) + self.manager.disable() + except ProcessExecutionError as process_err: + # self.manager.disable() will perform SIGTERM->wait->SIGKILL + # (if needed) on the process. However, it is sometimes possible + # that SIGKILL gets called on a process that just exited due to + # SIGTERM. Ignore this condition so the test is not marked as + # failed. + if not (len(process_err.args) > 0 and + "No such process" in process_err.args[0]): + raise def _prepare_devices(self): # NOTE(slaweq): those are devices used in keepalived config file, diff --git a/neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py b/neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py index 55d9329a88..a6457dcd0e 100644 --- a/neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py +++ b/neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py @@ -22,6 +22,7 @@ from neutron.agent.ovn.extensions import qos_hwol from neutron.common.ovn import constants as ovn_const from neutron.common.ovn import utils from neutron.common import utils as n_utils +from neutron.tests import base as test_base from neutron.tests.functional import base @@ -32,6 +33,7 @@ class OVSInterfaceEventTestCase(base.TestOVNFunctionalBase): check_error=False) self.ovs_idl.del_br(self.br_name).execute(check_error=False) + @test_base.unstable_test('bug 2006603') def test_port_creation_and_deletion(self): def check_add_port_called(): try: diff --git a/neutron/tests/functional/agent/ovn/metadata/test_metadata_agent.py b/neutron/tests/functional/agent/ovn/metadata/test_metadata_agent.py index bfa4747038..d0d4aebac3 100644 --- a/neutron/tests/functional/agent/ovn/metadata/test_metadata_agent.py +++ b/neutron/tests/functional/agent/ovn/metadata/test_metadata_agent.py @@ -51,6 +51,18 @@ class MetadataAgentHealthEvent(event.WaitEvent): ovn_const.OVN_AGENT_METADATA_SB_CFG_KEY, 0)) >= self.sb_cfg +class MetadataPortCreateEvent(event.WaitEvent): + event_name = 'MetadataPortCreateEvent' + + def __init__(self, metadata_port, timeout=5): + table = 'Port_Binding' + events = (self.ROW_CREATE,) + conditions = (('logical_port', '=', metadata_port),) + super(MetadataPortCreateEvent, self).__init__( + events, table, conditions, timeout=timeout + ) + + class TestMetadataAgent(base.TestOVNFunctionalBase): OVN_BRIDGE = 'br-int' FAKE_CHASSIS_HOST = 'ovn-host-fake' @@ -132,8 +144,8 @@ class TestMetadataAgent(base.TestOVNFunctionalBase): # chassis with the nb_cfg, 1 revisions when listing the agents. self.assertTrue(row_event.wait()) - def _create_metadata_port(self, txn, lswitch_name): - mdt_port_name = 'ovn-mdt-' + uuidutils.generate_uuid() + def _create_metadata_port(self, txn, lswitch_name, port_name=None): + mdt_port_name = port_name or 'ovn-mdt-' + uuidutils.generate_uuid() txn.add( self.nb_api.lsp_add( lswitch_name, @@ -144,7 +156,6 @@ class TestMetadataAgent(base.TestOVNFunctionalBase): ovn_const.OVN_CIDRS_EXT_ID_KEY: '192.168.122.123/24', ovn_const.OVN_DEVID_EXT_ID_KEY: 'ovnmeta-' + lswitch_name })) - return mdt_port_name def _update_metadata_port_ip(self, metadata_port_name): external_ids = { @@ -224,7 +235,14 @@ class TestMetadataAgent(base.TestOVNFunctionalBase): if update and type_ == ovn_const.LSP_TYPE_LOCALPORT: with self.nb_api.transaction( check_error=True, log_errors=True) as txn: - mdt_port_name = self._create_metadata_port(txn, lswitch_name) + mdt_port_name = 'ovn-mdt-' + uuidutils.generate_uuid() + metadata_port_create_event = MetadataPortCreateEvent( + mdt_port_name) + self.agent.sb_idl.idl.notify_handler.watch_event( + metadata_port_create_event) + self._create_metadata_port(txn, lswitch_name, mdt_port_name) + self.assertTrue(metadata_port_create_event.wait()) + self.sb_api.lsp_bind(mdt_port_name, self.chassis_name).execute( check_error=True, log_errors=True) self._update_metadata_port_ip(mdt_port_name) diff --git a/neutron/tests/functional/agent/test_ovs_lib.py b/neutron/tests/functional/agent/test_ovs_lib.py index b8968d86c0..056369a02d 100644 --- a/neutron/tests/functional/agent/test_ovs_lib.py +++ b/neutron/tests/functional/agent/test_ovs_lib.py @@ -489,7 +489,7 @@ class OVSBridgeTestCase(OVSBridgeTestBase): txn.add(ovsdb.del_port(port_name, self.br.br_name, if_exists=False)) txn.add(ovsdb.db_set('Interface', port_name, - ('type', 'internal'))) + ('type', 'internal'), if_exists=False)) self.assertRaises((RuntimeError, idlutils.RowNotFound), del_port_mod_iface) diff --git a/neutron/tests/functional/base.py b/neutron/tests/functional/base.py index 8321c2a6ee..8ef793989e 100644 --- a/neutron/tests/functional/base.py +++ b/neutron/tests/functional/base.py @@ -21,13 +21,9 @@ from unittest import mock import warnings import fixtures -from neutron_lib import fixture from neutron_lib.plugins import constants from neutron_lib.plugins import directory -from oslo_concurrency import lockutils from oslo_config import cfg -from oslo_db import exception as os_db_exc -from oslo_db.sqlalchemy import provision from oslo_log import log from oslo_utils import timeutils from oslo_utils import uuidutils @@ -61,7 +57,6 @@ LOG = log.getLogger(__name__) # This is the directory from which infra fetches log files for functional tests DEFAULT_LOG_DIR = os.path.join(helpers.get_test_log_path(), 'dsvm-functional-logs') -SQL_FIXTURE_LOCK = 'sql_fixture_lock' def config_decorator(method_to_decorate, config_tuples): @@ -134,27 +129,6 @@ class BaseSudoTestCase(BaseLoggingTestCase): new=ovs_agent_decorator).start() -class OVNSqlFixture(fixture.StaticSqlFixture): - - @classmethod - @lockutils.synchronized(SQL_FIXTURE_LOCK) - def _init_resources(cls): - cls.schema_resource = provision.SchemaResource( - provision.DatabaseResource("sqlite"), - cls._generate_schema, teardown=False) - dependency_resources = {} - for name, resource in cls.schema_resource.resources: - dependency_resources[name] = resource.getResource() - cls.schema_resource.make(dependency_resources) - cls.engine = dependency_resources['database'].engine - - def _delete_from_schema(self, engine): - try: - super(OVNSqlFixture, self)._delete_from_schema(engine) - except os_db_exc.DBNonExistentTable: - pass - - class TestOVNFunctionalBase(test_plugin.Ml2PluginV2TestCase, BaseLoggingTestCase): @@ -251,16 +225,6 @@ class TestOVNFunctionalBase(test_plugin.Ml2PluginV2TestCase, raise FileNotFoundError( errno.ENOENT, os.strerror(errno.ENOENT), msg) - # FIXME(lucasagomes): Workaround for - # https://bugs.launchpad.net/networking-ovn/+bug/1808146. We should - # investigate and properly fix the problem. This method is just a - # workaround to alleviate the gate for now and should not be considered - # a proper fix. - def _setup_database_fixtures(self): - fixture = OVNSqlFixture() - self.useFixture(fixture) - self.engine = fixture.engine - def get_additional_service_plugins(self): p = super(TestOVNFunctionalBase, self).get_additional_service_plugins() p.update({'revision_plugin_name': 'revisions', diff --git a/neutron/tests/functional/db/test_network.py b/neutron/tests/functional/db/test_network.py index 550a719a95..cebede36b2 100644 --- a/neutron/tests/functional/db/test_network.py +++ b/neutron/tests/functional/db/test_network.py @@ -20,6 +20,7 @@ from neutron_lib import exceptions as n_exc from oslo_config import cfg from oslo_utils import uuidutils +from neutron.db import rbac_db_models from neutron.objects import network as network_obj from neutron.plugins.ml2 import plugin as ml2_plugin from neutron import quota @@ -96,9 +97,9 @@ class NetworkRBACTestCase(testlib_api.SqlTestCase): def _check_rbac(self, network_id, is_none, external): if external: - action = 'access_as_external' + action = rbac_db_models.ACCESS_EXTERNAL else: - action = 'access_as_shared' + action = rbac_db_models.ACCESS_SHARED rbac = network_obj.NetworkRBAC.get_object( self.ctx, object_id=network_id, action=action, target_project='*') if is_none: diff --git a/neutron/tests/functional/pecan_wsgi/test_functional.py b/neutron/tests/functional/pecan_wsgi/test_functional.py index f5b5c7eb33..4698acf201 100644 --- a/neutron/tests/functional/pecan_wsgi/test_functional.py +++ b/neutron/tests/functional/pecan_wsgi/test_functional.py @@ -43,8 +43,11 @@ class InjectContext(base.ConfigurableMiddleware): # Determine the tenant tenant_id = req.headers.get('X_PROJECT_ID') - # Suck out the roles - roles = [r.strip() for r in req.headers.get('X_ROLES', '').split(',')] + roles = ['member', 'reader'] + # Suck out the roles if any are set + custom_roles = req.headers.get('X_ROLES') + if custom_roles: + roles = [r.strip() for r in custom_roles.split(',')] # Human-friendly names tenant_name = req.headers.get('X_PROJECT_NAME') diff --git a/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py b/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py index 85f33b6276..8edcf60b11 100644 --- a/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py +++ b/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_qos.py @@ -226,6 +226,7 @@ class TestOVNClientQosExtensionEndToEnd(TestOVNClientQosExtensionBase): arg_list = arg_list + (pnet.PHYSICAL_NETWORK,) net_arg[pnet.PHYSICAL_NETWORK] = physnet network = self._make_network(self.fmt, name, True, + as_admin=True, arg_list=arg_list, **net_arg) if cidr: self._make_subnet(self.fmt, network, gateway, cidr, diff --git a/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_maintenance.py b/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_maintenance.py index 6a23b3cc32..6cd025045f 100644 --- a/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_maintenance.py +++ b/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_maintenance.py @@ -30,9 +30,15 @@ from neutron.conf.plugins.ml2.drivers.ovn import ovn_conf as ovn_config from neutron.db import ovn_revision_numbers_db as db_rev from neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb import maintenance from neutron.tests.functional import base +from neutron.tests.functional.services.logapi.drivers.ovn \ + import test_driver as test_log_driver + from neutron.tests.unit.api import test_extensions from neutron.tests.unit.extensions import test_extraroute +CFG_NEW_BURST = 50 +CFG_NEW_RATE = 150 + class _TestMaintenanceHelper(base.TestOVNFunctionalBase): """A helper class to keep the code more organized.""" @@ -55,9 +61,9 @@ class _TestMaintenanceHelper(base.TestOVNFunctionalBase): return row def _create_network(self, name, external=False): - data = {'network': {'name': name, 'tenant_id': self._tenant_id, - extnet_apidef.EXTERNAL: external}} - req = self.new_create_request('networks', data, self.fmt) + data = {'network': {'name': name, extnet_apidef.EXTERNAL: external}} + req = self.new_create_request('networks', data, self.fmt, + as_admin=True) res = req.get_response(self.api) return self.deserialize(self.fmt, res)['network'] @@ -70,7 +76,6 @@ class _TestMaintenanceHelper(base.TestOVNFunctionalBase): def _create_port(self, name, net_id, security_groups=None, device_owner=None): data = {'port': {'name': name, - 'tenant_id': self._tenant_id, 'network_id': net_id}} if security_groups is not None: @@ -125,7 +130,6 @@ class _TestMaintenanceHelper(base.TestOVNFunctionalBase): data = {'subnet': {'name': name, 'network_id': net_id, 'ip_version': ip_version, - 'tenant_id': self._tenant_id, 'cidr': cidr, 'enable_dhcp': True}} data['subnet'].update(kwargs) @@ -146,10 +150,13 @@ class _TestMaintenanceHelper(base.TestOVNFunctionalBase): return row def _create_router(self, name, external_gateway_info=None): - data = {'router': {'name': name, 'tenant_id': self._tenant_id}} + data = {'router': {'name': name}} + as_admin = False if external_gateway_info is not None: data['router']['external_gateway_info'] = external_gateway_info - req = self.new_create_request('routers', data, self.fmt) + as_admin = bool(external_gateway_info.get('enable_snat')) + req = self.new_create_request('routers', data, self.fmt, + as_admin=as_admin) res = req.get_response(self.api) return self.deserialize(self.fmt, res)['router'] @@ -167,7 +174,6 @@ class _TestMaintenanceHelper(base.TestOVNFunctionalBase): def _create_security_group(self): data = {'security_group': {'name': 'sgtest', - 'tenant_id': self._tenant_id, 'description': 'SpongeBob Rocks!'}} req = self.new_create_request('security-groups', data, self.fmt) res = req.get_response(self.api) @@ -183,8 +189,7 @@ class _TestMaintenanceHelper(base.TestOVNFunctionalBase): 'protocol': n_const.PROTO_NAME_TCP, 'ethertype': n_const.IPv4, 'port_range_min': 22, - 'port_range_max': 22, - 'tenant_id': self._tenant_id}} + 'port_range_max': 22}} req = self.new_create_request('security-group-rules', data, self.fmt) res = req.get_response(self.api) return self.deserialize(self.fmt, res)['security_group_rule'] @@ -772,8 +777,8 @@ class TestMaintenance(_TestMaintenanceHelper): p1 = self._create_port('testp1', net1['id']) logical_ip = p1['fixed_ips'][0]['ip_address'] fip_info = {'floatingip': { - 'description': 'test_fip', 'tenant_id': self._tenant_id, + 'description': 'test_fip', 'floating_network_id': ext_net['id'], 'port_id': p1['id'], 'fixed_ip_address': logical_ip}} @@ -943,3 +948,37 @@ class TestMaintenance(_TestMaintenanceHelper): # Assert load balancer for port forwarding is gone self.assertFalse(self._find_pf_lb(router_id, fip_id)) + + +class TestLogMaintenance(_TestMaintenanceHelper, + test_log_driver.LogApiTestCaseBase): + def test_check_for_logging_conf_change(self): + # Check logging is supported + if not self.log_driver.network_logging_supported(self.nb_api): + self.skipTest("The current OVN version does not offer support " + "for neutron network log functionality.") + self.assertIsNotNone(self.log_plugin) + # Check no meter exists + self.assertFalse(self.nb_api._tables['Meter'].rows.values()) + # Add a log object + self.log_plugin.create_log(self.context, self._log_data()) + # Check a meter and fair meter exist + self.assertTrue(self.nb_api._tables['Meter'].rows) + self.assertTrue(self.nb_api._tables['Meter_Band'].rows) + self.assertEqual(cfg.CONF.network_log.burst_limit, + [*self.nb_api._tables['Meter_Band'].rows.values()][0].burst_size) + self.assertEqual(cfg.CONF.network_log.rate_limit, + [*self.nb_api._tables['Meter_Band'].rows.values()][0].rate) + # Update burst and rate limit values on the configuration + ovn_config.cfg.CONF.set_override('burst_limit', CFG_NEW_BURST, + group='network_log') + ovn_config.cfg.CONF.set_override('rate_limit', CFG_NEW_RATE, + group='network_log') + # Call the maintenance task + self.assertRaises(periodics.NeverAgain, + self.maint.check_fair_meter_consistency) + # Check meter band was effectively changed after the maintenance call + self.assertEqual(CFG_NEW_BURST, + [*self.nb_api._tables['Meter_Band'].rows.values()][0].burst_size) + self.assertEqual(CFG_NEW_RATE, + [*self.nb_api._tables['Meter_Band'].rows.values()][0].rate) diff --git a/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_db_sync.py b/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_db_sync.py index 892280f3bc..67aee6ba9a 100644 --- a/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_db_sync.py +++ b/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_db_sync.py @@ -365,7 +365,7 @@ class TestOvnNbSync(base.TestOVNFunctionalBase): port_req.get_response(self.api) # External network and subnet - e1 = self._make_network(self.fmt, 'e1', True, + e1 = self._make_network(self.fmt, 'e1', True, as_admin=True, arg_list=('router:external', 'provider:network_type', 'provider:physical_network'), @@ -1608,20 +1608,23 @@ class TestOvnNbSync(base.TestOVNFunctionalBase): net = self.deserialize(self.fmt, res)['network'] self._create_subnet(self.fmt, net['id'], '10.0.0.0/24') - res = self._create_qos_policy(self.fmt, 'qos_maxbw') + res = self._create_qos_policy(self.fmt, 'qos_maxbw', is_admin=True) qos_maxbw = self.deserialize(self.fmt, res)['policy'] self._create_qos_rule(self.fmt, qos_maxbw['id'], qos_const.RULE_TYPE_BANDWIDTH_LIMIT, - max_kbps=1000, max_burst_kbps=800) + max_kbps=1000, max_burst_kbps=800, + is_admin=True) self._create_qos_rule(self.fmt, qos_maxbw['id'], qos_const.RULE_TYPE_BANDWIDTH_LIMIT, direction=constants.INGRESS_DIRECTION, - max_kbps=700, max_burst_kbps=600) + max_kbps=700, max_burst_kbps=600, + is_admin=True) - res = self._create_qos_policy(self.fmt, 'qos_maxbw') + res = self._create_qos_policy(self.fmt, 'qos_maxbw', is_admin=True) qos_dscp = self.deserialize(self.fmt, res)['policy'] self._create_qos_rule(self.fmt, qos_dscp['id'], - qos_const.RULE_TYPE_DSCP_MARKING, dscp_mark=14) + qos_const.RULE_TYPE_DSCP_MARKING, dscp_mark=14, + is_admin=True) res = self._create_port( self.fmt, net['id'], arg_list=('qos_policy_id', ), @@ -1677,7 +1680,7 @@ class TestOvnNbSync(base.TestOVNFunctionalBase): {'floatingip': body}) def test_sync_fip_qos_policies(self): - res = self._create_network(self.fmt, 'n1_ext', True, + res = self._create_network(self.fmt, 'n1_ext', True, as_admin=True, arg_list=('router:external', ), **{'router:external': True}) net_ext = self.deserialize(self.fmt, res)['network'] @@ -1687,15 +1690,17 @@ class TestOvnNbSync(base.TestOVNFunctionalBase): net_int = self.deserialize(self.fmt, res)['network'] self._create_subnet(self.fmt, net_int['id'], '10.10.0.0/24') - res = self._create_qos_policy(self.fmt, 'qos_maxbw') + res = self._create_qos_policy(self.fmt, 'qos_maxbw', is_admin=True) qos_maxbw = self.deserialize(self.fmt, res)['policy'] self._create_qos_rule(self.fmt, qos_maxbw['id'], qos_const.RULE_TYPE_BANDWIDTH_LIMIT, - max_kbps=1000, max_burst_kbps=800) + max_kbps=1000, max_burst_kbps=800, + is_admin=True) self._create_qos_rule(self.fmt, qos_maxbw['id'], qos_const.RULE_TYPE_BANDWIDTH_LIMIT, direction=constants.INGRESS_DIRECTION, - max_kbps=700, max_burst_kbps=600) + max_kbps=700, max_burst_kbps=600, + is_admin=True) # Create a router with net_ext as GW network and net_int as internal # one, and a floating IP on the external network. @@ -1750,7 +1755,7 @@ class TestOvnNbSync(base.TestOVNFunctionalBase): self._validate_qos_records() def test_fip_nat_revert_to_stateful(self): - res = self._create_network(self.fmt, 'n1_ext', True, + res = self._create_network(self.fmt, 'n1_ext', True, as_admin=True, arg_list=('router:external', ), **{'router:external': True}) net_ext = self.deserialize(self.fmt, res)['network'] diff --git a/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovsdb_monitor.py b/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovsdb_monitor.py index 5a6073cfb2..1eea038c01 100644 --- a/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovsdb_monitor.py +++ b/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovsdb_monitor.py @@ -103,12 +103,13 @@ class TestNBDbMonitor(base.TestOVNFunctionalBase): allowedaddresspairs.ADDRESS_PAIRS: allowed_address_pairs } port_res = self._create_port(self.fmt, self.net['network']['id'], + is_admin=True, arg_list=arg_list, **host_arg) port = self.deserialize(self.fmt, port_res)['port'] return port def _create_fip(self, port, fip_address): - e1 = self._make_network(self.fmt, 'e1', True, + e1 = self._make_network(self.fmt, 'e1', True, as_admin=True, arg_list=('router:external', 'provider:network_type', 'provider:physical_network'), @@ -403,7 +404,8 @@ class TestSBDbMonitor(base.TestOVNFunctionalBase, test_l3.L3NatTestCaseMixin): kwargs = {'arg_list': (external_net.EXTERNAL,), external_net.EXTERNAL: True} - ext_net = self._make_network(self.fmt, 'ext_net', True, **kwargs) + ext_net = self._make_network(self.fmt, 'ext_net', True, as_admin=True, + **kwargs) self._make_subnet(self.fmt, ext_net, '10.251.0.1', '10.251.0.0/24', enable_dhcp=True) router = self._make_router(self.fmt, self._tenant_id) diff --git a/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py b/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py index 18f3f0d554..e1abd67c8e 100644 --- a/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py +++ b/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py @@ -101,20 +101,21 @@ class TestPortBinding(base.TestOVNFunctionalBase): 'network_id': self.n1['network']['id'], 'tenant_id': self._tenant_id}) - port_req = self.new_create_request('ports', port_data, self.fmt) + port_req = self.new_create_request('ports', port_data, self.fmt, + as_admin=True) port_res = port_req.get_response(self.api) p = self.deserialize(self.fmt, port_res) port_id = p['port']['id'] else: port_req = self.new_update_request('ports', port_data, port_id, - self.fmt) + self.fmt, as_admin=True) port_res = port_req.get_response(self.api) self.deserialize(self.fmt, port_res) return port_id def _port_show(self, port_id): - port_req = self.new_show_request('ports', port_id) + port_req = self.new_show_request('ports', port_id, as_admin=True) port_res = port_req.get_response(self.api) return self.deserialize(self.fmt, port_res) @@ -715,13 +716,13 @@ class TestExternalPorts(base.TestOVNFunctionalBase): def _test_external_port_create_switchdev(self, vnic_type): port_data = { 'port': {'network_id': self.n1['network']['id'], - 'tenant_id': self._tenant_id, portbindings.VNIC_TYPE: vnic_type, ovn_const.OVN_PORT_BINDING_PROFILE: { ovn_const.PORT_CAP_PARAM: [ ovn_const.PORT_CAP_SWITCHDEV]}}} - port_req = self.new_create_request('ports', port_data, self.fmt) + port_req = self.new_create_request('ports', port_data, self.fmt, + as_admin=True) port_res = port_req.get_response(self.api) port = self.deserialize(self.fmt, port_res)['port'] @@ -769,7 +770,8 @@ class TestExternalPorts(base.TestOVNFunctionalBase): ovn_const.PORT_CAP_PARAM: [ ovn_const.PORT_CAP_SWITCHDEV]}}} port_req = self.new_update_request( - 'ports', port_upt_data, port['id'], self.fmt) + 'ports', port_upt_data, port['id'], self.fmt, + as_admin=True) port_res = port_req.get_response(self.api) port = self.deserialize(self.fmt, port_res)['port'] @@ -948,7 +950,7 @@ class TestProvnetPorts(base.TestOVNFunctionalBase): def test_network_segments_localnet_ports(self): n1 = self._make_network( - self.fmt, 'n1', True, + self.fmt, 'n1', True, as_admin=True, arg_list=('provider:network_type', 'provider:segmentation_id', 'provider:physical_network'), @@ -995,6 +997,7 @@ class TestMetadataPorts(base.TestOVNFunctionalBase): def setUp(self, *args, **kwargs): super().setUp(*args, **kwargs) + self.plugin = self.mech_driver._plugin self._ovn_client = self.mech_driver._ovn_client self.meta_regex = re.compile(r'%s,(\d+\.\d+\.\d+\.\d+)' % constants.METADATA_V4_CIDR) @@ -1017,7 +1020,7 @@ class TestMetadataPorts(base.TestOVNFunctionalBase): res = self._list_ports(self.fmt, net_id=net_id) return self.deserialize(self.fmt, res)['ports'] - def _check_metadata_port(self, net_id, fixed_ip): + def _check_metadata_port(self, net_id, fixed_ip, fail=True): for port in self._list_ports_ovn(net_id=net_id): if ovn_client.OVNClient.is_metadata_port(port): self.assertEqual(net_id, port['network_id']) @@ -1027,13 +1030,17 @@ class TestMetadataPorts(base.TestOVNFunctionalBase): self.assertEqual([], port['fixed_ips']) return port['id'] - self.fail('Metadata port is not present in network %s or data is not ' - 'correct' % self.n1_id) + if fail: + self.fail('Metadata port is not present in network %s or data is ' + 'not correct' % self.n1_id) def _check_subnet_dhcp_options(self, subnet_id, cidr): - # This method checks the DHCP options CIDR and returns, if exits, the - # metadata port IP address, included in the classless static routes. + # This method checks DHCP options for a subnet ID, and if they exist, + # verifies the CIDR matches. Returns the metadata port IP address + # if it is included in the classless static routes, else returns None. dhcp_opts = self._ovn_client._nb_idl.get_subnet_dhcp_options(subnet_id) + if not dhcp_opts['subnet']: + return self.assertEqual(cidr, dhcp_opts['subnet']['cidr']) routes = dhcp_opts['subnet']['options'].get('classless_static_route') if not routes: @@ -1062,6 +1069,35 @@ class TestMetadataPorts(base.TestOVNFunctionalBase): fixed_ip = {'subnet_id': subnet['id'], 'ip_address': metatada_ip} self._check_metadata_port(self.n1_id, fixed_ip) + def test_update_subnet_ipv4(self): + self._create_network_ovn(metadata_enabled=True) + subnet = self._create_subnet_ovn('10.0.0.0/24') + metatada_ip = self._check_subnet_dhcp_options(subnet['id'], + '10.0.0.0/24') + fixed_ip = {'subnet_id': subnet['id'], 'ip_address': metatada_ip} + port_id = self._check_metadata_port(self.n1_id, fixed_ip) + + # Disable DHCP, port should still be present + subnet['enable_dhcp'] = False + self._ovn_client.update_subnet(self.context, subnet, + self.n1['network']) + port_id = self._check_metadata_port(self.n1_id, None) + self.assertIsNone(self._check_subnet_dhcp_options(subnet['id'], [])) + + # Delete metadata port + self.plugin.delete_port(self.context, port_id) + port_id = self._check_metadata_port(self.n1_id, None, fail=False) + self.assertIsNone(port_id) + + # Enable DHCP, metadata port should have been re-created + subnet['enable_dhcp'] = True + self._ovn_client.update_subnet(self.context, subnet, + self.n1['network']) + metatada_ip = self._check_subnet_dhcp_options(subnet['id'], + '10.0.0.0/24') + fixed_ip = {'subnet_id': subnet['id'], 'ip_address': metatada_ip} + port_id = self._check_metadata_port(self.n1_id, fixed_ip) + def test_subnet_ipv4_no_metadata(self): self._create_network_ovn(metadata_enabled=False) subnet = self._create_subnet_ovn('10.0.0.0/24') diff --git a/neutron/tests/functional/plugins/ml2/test_plugin.py b/neutron/tests/functional/plugins/ml2/test_plugin.py index 667ef651a4..16fde03b09 100644 --- a/neutron/tests/functional/plugins/ml2/test_plugin.py +++ b/neutron/tests/functional/plugins/ml2/test_plugin.py @@ -50,6 +50,7 @@ class TestMl2PortBinding(ml2_test_base.ML2TestFramework, with self.subnet(network=network) as subnet: with self.port( subnet=subnet, device_owner=DEVICE_OWNER_COMPUTE, + is_admin=True, arg_list=(portbindings.HOST_ID, 'admin_state_up',), **self.host_args) as port: # Note: Port creation invokes _bind_port_if_needed(), @@ -65,6 +66,7 @@ class TestMl2PortBinding(ml2_test_base.ML2TestFramework, with self.subnet(network=network) as subnet: with self.port( subnet=subnet, device_owner=DEVICE_OWNER_COMPUTE, + is_admin=True, arg_list=(portbindings.HOST_ID, 'admin_state_up',), **self.host_args) as port: # Since the agent is dead, expect binding to fail @@ -88,6 +90,7 @@ class TestMl2PortBinding(ml2_test_base.ML2TestFramework, with self.subnet(network=network) as subnet: with self.port( subnet=subnet, device_owner=DEVICE_OWNER_COMPUTE, + is_admin=True, arg_list=(portbindings.HOST_ID, 'admin_state_up',), **self.host_args) as port: pass diff --git a/neutron/tests/functional/services/l3_router/test_l3_dvr_ha_router_plugin.py b/neutron/tests/functional/services/l3_router/test_l3_dvr_ha_router_plugin.py index 0b6019fefb..ac2aac1cdc 100644 --- a/neutron/tests/functional/services/l3_router/test_l3_dvr_ha_router_plugin.py +++ b/neutron/tests/functional/services/l3_router/test_l3_dvr_ha_router_plugin.py @@ -134,21 +134,25 @@ class L3DvrHATestCase(test_l3_dvr_router_plugin.L3DvrTestCase): self.subnet(cidr='30.0.0.0/24') as subnet2, \ self.subnet(cidr='40.0.0.0/24') as subnet3, \ self.port(subnet=subnet1, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=arg_list, **{portbindings.HOST_ID: HOST1}), \ self.port(subnet=subnet2, + is_admin=True, device_owner=constants.DEVICE_OWNER_DHCP, arg_list=arg_list, **{portbindings.HOST_ID: HOST2}), \ self.port(subnet=subnet3, + is_admin=True, device_owner=constants.DEVICE_OWNER_NETWORK_PREFIX, arg_list=arg_list, **{portbindings.HOST_ID: HOST3}): # make net external ext_net_id = ext_subnet['subnet']['network_id'] self._update('networks', ext_net_id, - {'network': {extnet_apidef.EXTERNAL: True}}) + {'network': {extnet_apidef.EXTERNAL: True}}, + as_admin=True) with mock.patch.object(self.l3_plugin.l3_rpc_notifier.client, 'prepare') as mock_prepare: # add external gateway to router @@ -231,7 +235,7 @@ class L3DvrHATestCase(test_l3_dvr_router_plugin.L3DvrTestCase): kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} with self.subnet() as subnet, \ - self.network(**kwargs) as ext_net, \ + self.network(as_admin=True, **kwargs) as ext_net, \ self.subnet(network=ext_net, cidr='20.0.0.0/24'): gw_info = {'network_id': ext_net['network']['id']} self.l3_plugin.update_router( @@ -256,7 +260,7 @@ class L3DvrHATestCase(test_l3_dvr_router_plugin.L3DvrTestCase): router = self._create_router(distributed=True, ha=True) kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - with self.network(**kwargs) as ext_net, \ + with self.network(as_admin=True, **kwargs) as ext_net, \ self.subnet(network=ext_net), \ self.subnet(cidr='20.0.0.0/24') as subnet, \ self.port(subnet=subnet, @@ -300,7 +304,8 @@ class L3DvrHATestCase(test_l3_dvr_router_plugin.L3DvrTestCase): def _create_external_network(self): kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - ext_net = self._make_network(self.fmt, 'ext_net', True, **kwargs) + ext_net = self._make_network(self.fmt, 'ext_net', True, as_admin=True, + **kwargs) self._make_subnet( self.fmt, ext_net, '10.0.0.1', '10.0.0.0/24', ip_version=constants.IP_VERSION_4, enable_dhcp=True) diff --git a/neutron/tests/functional/services/l3_router/test_l3_dvr_router_plugin.py b/neutron/tests/functional/services/l3_router/test_l3_dvr_router_plugin.py index 17e37cda8d..097be093a3 100644 --- a/neutron/tests/functional/services/l3_router/test_l3_dvr_router_plugin.py +++ b/neutron/tests/functional/services/l3_router/test_l3_dvr_router_plugin.py @@ -24,7 +24,6 @@ from neutron_lib.callbacks import resources from neutron_lib.db import api as db_api from neutron_lib import constants -from neutron_lib import context from neutron.api.rpc.handlers import l3_rpc from neutron.tests.common import helpers @@ -112,7 +111,8 @@ class L3DvrTestCase(L3DvrTestCaseBase): self.fmt, net1, '10.1.0.1', '10.1.0.0/24', enable_dhcp=True) subnet2 = self._make_subnet( self.fmt, net1, '10.2.0.1', '10.2.0.0/24', enable_dhcp=True) - ext_net = self._make_network(self.fmt, 'ext_net', True, **kwargs) + ext_net = self._make_network(self.fmt, 'ext_net', True, as_admin=True, + **kwargs) self._make_subnet( self.fmt, ext_net, '20.0.0.1', '20.0.0.0/24', enable_dhcp=True) # Create first router and add an interface @@ -170,7 +170,7 @@ class L3DvrTestCase(L3DvrTestCaseBase): self.subnet(cidr='20.0.0.0/24') as subnet2: kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - with self.network(**kwargs) as ext_net, \ + with self.network(as_admin=True, **kwargs) as ext_net, \ self.subnet(network=ext_net, cidr='30.0.0.0/24'): router = self._create_router() @@ -287,7 +287,8 @@ class L3DvrTestCase(L3DvrTestCaseBase): self.fmt, net1, '10.1.0.1', '10.1.0.0/24', enable_dhcp=True) subnet2 = self._make_subnet( self.fmt, net2, '10.1.0.1', '10.1.0.0/24', enable_dhcp=True) - ext_net = self._make_network(self.fmt, 'ext_net', True, **kwargs) + ext_net = self._make_network(self.fmt, 'ext_net', True, as_admin=True, + **kwargs) self._make_subnet( self.fmt, ext_net, '20.0.0.1', '20.0.0.0/24', enable_dhcp=True) # Create first router and add an interface @@ -358,7 +359,8 @@ class L3DvrTestCase(L3DvrTestCaseBase): # make net external ext_net_id = ext_subnet['subnet']['network_id'] self._update('networks', ext_net_id, - {'network': {extnet_apidef.EXTERNAL: True}}) + {'network': {extnet_apidef.EXTERNAL: True}}, + as_admin=True) router = self._create_router(distributed=dvr) self.l3_plugin.update_router( @@ -447,7 +449,8 @@ class L3DvrTestCase(L3DvrTestCaseBase): # make net external ext_net_id = ext_subnet['subnet']['network_id'] self._update('networks', ext_net_id, - {'network': {extnet_apidef.EXTERNAL: True}}) + {'network': {extnet_apidef.EXTERNAL: True}}, + as_admin=True) router1 = self._create_router(distributed=dvr) router2 = self._create_router(distributed=dvr) @@ -559,7 +562,8 @@ class L3DvrTestCase(L3DvrTestCaseBase): # make net external ext_net_id = ext_subnet['subnet']['network_id'] self._update('networks', ext_net_id, - {'network': {extnet_apidef.EXTERNAL: True}}) + {'network': {extnet_apidef.EXTERNAL: True}}, + as_admin=True) router = self._create_router(distributed=dvr) self.l3_plugin.update_router( @@ -636,7 +640,8 @@ class L3DvrTestCase(L3DvrTestCaseBase): def test_router_with_ipv4_and_multiple_ipv6_on_same_network(self): kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - ext_net = self._make_network(self.fmt, '', True, **kwargs) + ext_net = self._make_network(self.fmt, '', True, as_admin=True, + **kwargs) self._make_subnet( self.fmt, ext_net, '10.0.0.1', '10.0.0.0/24', ip_version=constants.IP_VERSION_4, enable_dhcp=True) @@ -710,7 +715,8 @@ class L3DvrTestCase(L3DvrTestCaseBase): fixed_vrrp_ip = [{'ip_address': '10.1.0.201'}] kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - ext_net = self._make_network(self.fmt, '', True, **kwargs) + ext_net = self._make_network(self.fmt, '', True, as_admin=True, + **kwargs) self._make_subnet( self.fmt, ext_net, '10.20.0.1', '10.20.0.0/24', ip_version=constants.IP_VERSION_4, enable_dhcp=True) @@ -820,7 +826,8 @@ class L3DvrTestCase(L3DvrTestCaseBase): private_net1 = self._make_network(self.fmt, 'net1', True) kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - ext_net = self._make_network(self.fmt, '', True, **kwargs) + ext_net = self._make_network(self.fmt, '', True, as_admin=True, + **kwargs) self._make_subnet( self.fmt, ext_net, '10.20.0.1', '10.20.0.0/24', ip_version=constants.IP_VERSION_4, enable_dhcp=True) @@ -904,7 +911,8 @@ class L3DvrTestCase(L3DvrTestCaseBase): private_net1 = self._make_network(self.fmt, 'net1', True) kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - ext_net = self._make_network(self.fmt, '', True, **kwargs) + ext_net = self._make_network(self.fmt, '', True, as_admin=True, + **kwargs) self._make_subnet( self.fmt, ext_net, '10.20.0.1', '10.20.0.0/24', ip_version=constants.IP_VERSION_4, enable_dhcp=True) @@ -982,7 +990,8 @@ class L3DvrTestCase(L3DvrTestCaseBase): private_net1 = self._make_network(self.fmt, 'net1', True) kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - ext_net = self._make_network(self.fmt, '', True, **kwargs) + ext_net = self._make_network(self.fmt, '', True, as_admin=True, + **kwargs) self._make_subnet( self.fmt, ext_net, '10.20.0.1', '10.20.0.0/24', ip_version=constants.IP_VERSION_4, enable_dhcp=True) @@ -1067,7 +1076,8 @@ class L3DvrTestCase(L3DvrTestCaseBase): fixed_vrrp_ip = [{'ip_address': '10.1.0.201'}] kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - ext_net = self._make_network(self.fmt, '', True, **kwargs) + ext_net = self._make_network(self.fmt, '', True, as_admin=True, + **kwargs) self._make_subnet( self.fmt, ext_net, '10.20.0.1', '10.20.0.0/24', ip_version=constants.IP_VERSION_4, enable_dhcp=True) @@ -1200,7 +1210,8 @@ class L3DvrTestCase(L3DvrTestCaseBase): private_net1 = self._make_network(self.fmt, 'net1', True) kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - ext_net = self._make_network(self.fmt, '', True, **kwargs) + ext_net = self._make_network(self.fmt, '', True, as_admin=True, + **kwargs) self._make_subnet( self.fmt, ext_net, '10.20.0.1', '10.20.0.0/24', ip_version=constants.IP_VERSION_4, enable_dhcp=True) @@ -1243,7 +1254,8 @@ class L3DvrTestCase(L3DvrTestCaseBase): fixed_vrrp_ip = [{'ip_address': '10.1.0.201'}] kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - ext_net = self._make_network(self.fmt, '', True, **kwargs) + ext_net = self._make_network(self.fmt, '', True, as_admin=True, + **kwargs) self._make_subnet( self.fmt, ext_net, '10.20.0.1', '10.20.0.0/24', ip_version=constants.IP_VERSION_4, enable_dhcp=True) @@ -1382,7 +1394,7 @@ class L3DvrTestCase(L3DvrTestCaseBase): router = self._create_router() kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - with self.network(**kwargs) as ext_net,\ + with self.network(as_admin=True, **kwargs) as ext_net,\ self.subnet(network=ext_net),\ self.subnet(cidr='20.0.0.0/24') as subnet,\ self.port(subnet=subnet): @@ -1412,7 +1424,7 @@ class L3DvrTestCase(L3DvrTestCaseBase): router = self._create_router() kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - with self.network(**kwargs) as ext_net,\ + with self.network(as_admin=True, **kwargs) as ext_net,\ self.subnet(network=ext_net),\ self.subnet(cidr='20.0.0.0/24') as subnet,\ self.port(subnet=subnet, @@ -1450,7 +1462,7 @@ class L3DvrTestCase(L3DvrTestCaseBase): helpers.register_l3_agent( host=HOST, agent_mode=constants.L3_AGENT_MODE_DVR) router = self._create_router() - with self.network(shared=True) as net,\ + with self.network(as_admin=True, shared=True) as net,\ self.subnet(network=net) as subnet,\ self.port(subnet=subnet, device_owner=DEVICE_OWNER_COMPUTE, @@ -1465,9 +1477,8 @@ class L3DvrTestCase(L3DvrTestCaseBase): with mock.patch.object(self.l3_plugin.l3_rpc_notifier, 'router_removed_from_agent') as remove_mock: - ctx = context.Context( - '', non_admin_tenant) if non_admin_port else self.context - self._delete('ports', port['port']['id'], neutron_context=ctx) + self._delete('ports', port['port']['id'], + tenant_id=non_admin_tenant) remove_mock.assert_called_once_with( mock.ANY, router['id'], HOST) @@ -1501,13 +1512,15 @@ class L3DvrTestCase(L3DvrTestCaseBase): with self.subnet() as ext_subnet,\ self.subnet(cidr='20.0.0.0/24') as subnet1,\ self.port(subnet=subnet1, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=arg_list, **{portbindings.HOST_ID: HOST1}) as vm_port: # make net external ext_net_id = ext_subnet['subnet']['network_id'] self._update('networks', ext_net_id, - {'network': {extnet_apidef.EXTERNAL: True}}) + {'network': {extnet_apidef.EXTERNAL: True}}, + as_admin=True) # add external gateway to router self.l3_plugin.update_router( self.context, router['id'], @@ -1576,21 +1589,25 @@ class L3DvrTestCase(L3DvrTestCaseBase): self.subnet(cidr='30.0.0.0/24') as subnet2,\ self.subnet(cidr='40.0.0.0/24') as subnet3,\ self.port(subnet=subnet1, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=arg_list, **{portbindings.HOST_ID: HOST1}),\ self.port(subnet=subnet2, + is_admin=True, device_owner=constants.DEVICE_OWNER_DHCP, arg_list=arg_list, **{portbindings.HOST_ID: HOST2}),\ self.port(subnet=subnet3, + is_admin=True, device_owner=constants.DEVICE_OWNER_NETWORK_PREFIX, arg_list=arg_list, **{portbindings.HOST_ID: HOST3}): # make net external ext_net_id = ext_subnet['subnet']['network_id'] self._update('networks', ext_net_id, - {'network': {extnet_apidef.EXTERNAL: True}}) + {'network': {extnet_apidef.EXTERNAL: True}}, + as_admin=True) with mock.patch.object(self.l3_plugin.l3_rpc_notifier.client, 'prepare') as mock_prepare: @@ -1661,7 +1678,7 @@ class L3DvrTestCase(L3DvrTestCaseBase): kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} with self.subnet() as subnet,\ - self.network(**kwargs) as ext_net,\ + self.network(as_admin=True, **kwargs) as ext_net,\ self.subnet(network=ext_net, cidr='20.0.0.0/24'): gw_info = {'network_id': ext_net['network']['id']} request_body = { @@ -1693,7 +1710,7 @@ class L3DvrTestCase(L3DvrTestCaseBase): router = self._create_router() kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - with self.network(**kwargs) as ext_net,\ + with self.network(as_admin=True, **kwargs) as ext_net,\ self.subnet(network=ext_net),\ self.subnet(cidr='20.0.0.0/24') as subnet,\ self.port(subnet=subnet, @@ -1796,10 +1813,12 @@ class L3DvrTestCase(L3DvrTestCaseBase): with self.subnet(cidr='20.0.0.0/24') as subnet1,\ self.subnet(cidr='30.0.0.0/24') as subnet2,\ self.port(subnet=subnet1, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=arg_list, **{portbindings.HOST_ID: host}),\ self.port(subnet=subnet2, + is_admin=True, device_owner=constants.DEVICE_OWNER_DHCP, arg_list=arg_list, **{portbindings.HOST_ID: host}): @@ -1834,10 +1853,12 @@ class L3DvrTestCase(L3DvrTestCaseBase): self.subnet(cidr='20.0.0.0/24') as subnet1,\ self.subnet(cidr='30.0.0.0/24') as subnet2,\ self.port(subnet=subnet1, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=arg_list, **{portbindings.HOST_ID: host}),\ self.port(subnet=subnet2, + is_admin=True, device_owner=constants.DEVICE_OWNER_DHCP, arg_list=arg_list, **{portbindings.HOST_ID: host}): @@ -1883,7 +1904,8 @@ class L3DvrTestCase(L3DvrTestCaseBase): # make net external ext_net_id = ext_subnet['subnet']['network_id'] self._update('networks', ext_net_id, - {'network': {extnet_apidef.EXTERNAL: True}}) + {'network': {extnet_apidef.EXTERNAL: True}}, + as_admin=True) # add external gateway to router self.l3_plugin.update_router( self.context, router3['id'], @@ -1915,6 +1937,7 @@ class L3DvrTestCase(L3DvrTestCaseBase): self.port(subnet=wan_subnet) as wan_port1,\ self.port(subnet=wan_subnet) as wan_port2,\ self.port(subnet=subnet1, + is_admin=True, device_owner=constants.DEVICE_OWNER_DHCP, arg_list=arg_list, **{portbindings.HOST_ID: host}): @@ -1958,6 +1981,7 @@ class L3DvrTestCase(L3DvrTestCaseBase): arg_list = (portbindings.HOST_ID,) with self.subnet() as subnet,\ self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=arg_list, **{portbindings.HOST_ID: HOST1}): @@ -2067,7 +2091,7 @@ class L3DvrTestCaseMigration(L3DvrTestCaseBase): with self.subnet() as subnet1: kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - with self.network(**kwargs) as ext_net, \ + with self.network(as_admin=True, **kwargs) as ext_net, \ self.subnet(network=ext_net, cidr='30.0.0.0/24'): router = self._create_router(distributed=False) diff --git a/neutron/tests/functional/services/logapi/drivers/ovn/test_driver.py b/neutron/tests/functional/services/logapi/drivers/ovn/test_driver.py index 57c7978b8f..fb5bd58c68 100644 --- a/neutron/tests/functional/services/logapi/drivers/ovn/test_driver.py +++ b/neutron/tests/functional/services/logapi/drivers/ovn/test_driver.py @@ -28,7 +28,7 @@ class LogApiTestCaseBase(functional_base.TestOVNFunctionalBase): super().setUp() self.log_driver = self.mech_driver.log_driver self._check_is_supported() - self.ctxt = context.Context('admin', 'fake_tenant') + self.ctxt = context.Context('admin', self._tenant_id) def _check_is_supported(self): if not self.log_driver.network_logging_supported(self.nb_api): @@ -110,7 +110,6 @@ class LogApiTestCaseComplex(LogApiTestCaseBase): def _create_port(self, name, net_id, security_groups): data = {'port': {'name': name, - 'tenant_id': self.ctxt.project_id, 'network_id': net_id, 'security_groups': security_groups}} req = self.new_create_request('ports', data, self.fmt) @@ -118,8 +117,7 @@ class LogApiTestCaseComplex(LogApiTestCaseBase): return self.deserialize(self.fmt, res)['port']['id'] def _create_security_group(self, name): - data = {'security_group': {'name': name, - 'tenant_id': self.ctxt.project_id}} + data = {'security_group': {'name': name}} req = self.new_create_request('security-groups', data, self.fmt) res = req.get_response(self.api) return self.deserialize(self.fmt, res)['security_group']['id'] @@ -130,8 +128,7 @@ class LogApiTestCaseComplex(LogApiTestCaseBase): 'protocol': n_const.PROTO_NAME_TCP, 'ethertype': n_const.IPv4, 'port_range_min': tcp_port, - 'port_range_max': tcp_port, - 'tenant_id': self.ctxt.project_id}} + 'port_range_max': tcp_port}} req = self.new_create_request('security-group-rules', data, self.fmt) res = req.get_response(self.api) return self.deserialize(self.fmt, res)['security_group_rule']['id'] diff --git a/neutron/tests/functional/services/ovn_l3/test_plugin.py b/neutron/tests/functional/services/ovn_l3/test_plugin.py index 91859c02ef..fbaa0b8ade 100644 --- a/neutron/tests/functional/services/ovn_l3/test_plugin.py +++ b/neutron/tests/functional/services/ovn_l3/test_plugin.py @@ -63,7 +63,7 @@ class TestRouter(base.TestOVNFunctionalBase): if physnet: arg_list = arg_list + (pnet.PHYSICAL_NETWORK,) net_arg[pnet.PHYSICAL_NETWORK] = physnet - network = self._make_network(self.fmt, name, True, + network = self._make_network(self.fmt, name, True, as_admin=True, arg_list=arg_list, **net_arg) if cidr: self._make_subnet(self.fmt, network, gateway, cidr, diff --git a/neutron/tests/functional/services/portforwarding/test_port_forwarding.py b/neutron/tests/functional/services/portforwarding/test_port_forwarding.py index 9881c1c4a0..e0b4dbf733 100644 --- a/neutron/tests/functional/services/portforwarding/test_port_forwarding.py +++ b/neutron/tests/functional/services/portforwarding/test_port_forwarding.py @@ -98,7 +98,8 @@ class PortForwardingTestCase(PortForwardingTestCaseBase): def _prepare_env(self): self.router = self._create_router(distributed=True) self.ext_net = self._create_network( - self.fmt, 'ext-net', True, arg_list=("router:external",), + self.fmt, 'ext-net', True, as_admin=True, + arg_list=("router:external",), **{"router:external": True}).json['network'] self.ext_subnet = self._create_subnet( self.fmt, self.ext_net['id'], '172.24.2.0/24').json['subnet'] diff --git a/neutron/tests/unit/_test_extension_portbindings.py b/neutron/tests/unit/_test_extension_portbindings.py index ea18b96e10..763e28b6d8 100644 --- a/neutron/tests/unit/_test_extension_portbindings.py +++ b/neutron/tests/unit/_test_extension_portbindings.py @@ -55,24 +55,16 @@ class PortBindingsTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): self.assertNotIn(portbindings.VIF_TYPE, port) self.assertNotIn(portbindings.VIF_DETAILS, port) - def _get_non_admin_context(self): - return context.Context(user_id=None, - tenant_id=self._tenant_id, - is_admin=False) - def test_port_vif_details(self): - with self.port(name='name') as port: + with self.port(is_admin=True, name='name') as port: port_id = port['port']['id'] # Check a response of create_port self._check_response_portbindings(port['port']) # Check a response of get_port - ctx = context.get_admin_context() - port = self._show('ports', port_id, neutron_context=ctx)['port'] + port = self._show('ports', port_id, as_admin=True)['port'] self._check_response_portbindings(port) # By default user is admin - now test non admin user - ctx = self._get_non_admin_context() - non_admin_port = self._show( - 'ports', port_id, neutron_context=ctx)['port'] + non_admin_port = self._show('ports', port_id)['port'] self._check_response_no_portbindings(non_admin_port) def test_ports_vif_details(self): @@ -83,9 +75,7 @@ class PortBindingsTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): self.assertEqual(len(ports), 2) for port in ports: self._check_response_portbindings(port) - # By default user is admin - now test non admin user - ctx = self._get_non_admin_context() - ports = self._list('ports', neutron_context=ctx)['ports'] + ports = self._list('ports')['ports'] self.assertEqual(len(ports), 2) for non_admin_port in ports: self._check_response_no_portbindings(non_admin_port) @@ -97,11 +87,12 @@ class PortBindingsTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): def _test_create_port_binding_profile(self, profile): profile_arg = {portbindings.PROFILE: profile} - with self.port(arg_list=(portbindings.PROFILE,), + with self.port(is_admin=True, + arg_list=(portbindings.PROFILE,), **profile_arg) as port: port_id = port['port']['id'] self._check_port_binding_profile(port['port'], profile) - port = self._show('ports', port_id) + port = self._show('ports', port_id, as_admin=True) self._check_port_binding_profile(port['port'], profile) def test_create_port_binding_profile_none(self): @@ -112,14 +103,13 @@ class PortBindingsTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): def _test_update_port_binding_profile(self, profile): profile_arg = {portbindings.PROFILE: profile} - with self.port() as port: + with self.port(is_admin=True) as port: self._check_port_binding_profile(port['port']) port_id = port['port']['id'] - ctx = context.get_admin_context() port = self._update('ports', port_id, {'port': profile_arg}, - neutron_context=ctx)['port'] + as_admin=True)['port'] self._check_port_binding_profile(port, profile) - port = self._show('ports', port_id)['port'] + port = self._show('ports', port_id, as_admin=True)['port'] self._check_port_binding_profile(port, profile) def test_update_port_binding_profile_none(self): @@ -131,18 +121,16 @@ class PortBindingsTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): def test_port_create_portinfo_non_admin(self): profile_arg = {portbindings.PROFILE: {dummy_plugin.RESOURCE_NAME: dummy_plugin.RESOURCE_NAME}} - with self.network(set_context=True, tenant_id='test') as net1: + with self.network() as net1: with self.subnet(network=net1) as subnet1: # succeed without binding:profile - with self.port(subnet=subnet1, - set_context=True, tenant_id='test'): + with self.port(subnet=subnet1): pass # fail with binding:profile try: with self.port(subnet=subnet1, expected_res_status=403, arg_list=(portbindings.PROFILE,), - set_context=True, tenant_id='test', **profile_arg): pass except exc.HTTPClientError: @@ -156,11 +144,9 @@ class PortBindingsTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): with self.port(subnet=subnet1) as port: # By default user is admin - now test non admin user port_id = port['port']['id'] - ctx = self._get_non_admin_context() port = self._update('ports', port_id, {'port': profile_arg}, - expected_code=exc.HTTPForbidden.code, - neutron_context=ctx) + expected_code=exc.HTTPForbidden.code) class PortBindingsHostTestCaseMixin(object): @@ -192,74 +178,70 @@ class PortBindingsHostTestCaseMixin(object): def test_port_vif_host(self): host_arg = {portbindings.HOST_ID: self.hostname} - with self.port(name='name', arg_list=(portbindings.HOST_ID,), + with self.port(name='name', is_admin=True, + arg_list=(portbindings.HOST_ID,), **host_arg) as port: port_id = port['port']['id'] # Check a response of create_port self._check_response_portbindings_host(port['port']) # Check a response of get_port - ctx = context.get_admin_context() - port = self._show('ports', port_id, neutron_context=ctx)['port'] + port = self._show('ports', port_id, as_admin=True)['port'] self._check_response_portbindings_host(port) - # By default user is admin - now test non admin user - ctx = context.Context(user_id=None, - tenant_id=self._tenant_id, - is_admin=False) - non_admin_port = self._show( - 'ports', port_id, neutron_context=ctx)['port'] + non_admin_port = self._show('ports', port_id)['port'] self._check_response_no_portbindings_host(non_admin_port) def test_ports_vif_host(self): host_arg = {portbindings.HOST_ID: self.hostname} with self.port(name='name1', + is_admin=True, arg_list=(portbindings.HOST_ID,), **host_arg), self.port(name='name2'): - ctx = context.get_admin_context() - ports = self._list('ports', neutron_context=ctx)['ports'] + ports = self._list('ports', as_admin=True)['ports'] self.assertEqual(2, len(ports)) for port in ports: if port['name'] == 'name1': self._check_response_portbindings_host(port) else: self.assertFalse(port[portbindings.HOST_ID]) - # By default user is admin - now test non admin user - ctx = context.Context(user_id=None, - tenant_id=self._tenant_id, - is_admin=False) - ports = self._list('ports', neutron_context=ctx)['ports'] + ports = self._list('ports')['ports'] self.assertEqual(2, len(ports)) for non_admin_port in ports: self._check_response_no_portbindings_host(non_admin_port) def test_ports_vif_host_update(self): host_arg = {portbindings.HOST_ID: self.hostname} - with self.port(name='name1', arg_list=(portbindings.HOST_ID,), + with self.port(name='name1', is_admin=True, + arg_list=(portbindings.HOST_ID,), **host_arg) as port1, self.port(name='name2') as port2: data = {'port': {portbindings.HOST_ID: 'testhosttemp'}} - req = self.new_update_request('ports', data, port1['port']['id']) + req = self.new_update_request('ports', data, port1['port']['id'], + as_admin=True) req.get_response(self.api) - req = self.new_update_request('ports', data, port2['port']['id']) - ctx = context.get_admin_context() + req = self.new_update_request('ports', data, port2['port']['id'], + as_admin=True) req.get_response(self.api) - ports = self._list('ports', neutron_context=ctx)['ports'] + ports = self._list('ports', as_admin=True)['ports'] self.assertEqual(2, len(ports)) for port in ports: self.assertEqual('testhosttemp', port[portbindings.HOST_ID]) def test_ports_vif_non_host_update(self): host_arg = {portbindings.HOST_ID: self.hostname} - with self.port(name='name', arg_list=(portbindings.HOST_ID,), + with self.port(name='name', is_admin=True, + arg_list=(portbindings.HOST_ID,), **host_arg) as port: data = {'port': {'admin_state_up': False}} - req = self.new_update_request('ports', data, port['port']['id']) + req = self.new_update_request('ports', data, port['port']['id'], + as_admin=True) res = self.deserialize(self.fmt, req.get_response(self.api)) self.assertEqual(port['port'][portbindings.HOST_ID], res['port'][portbindings.HOST_ID]) def test_ports_vif_non_host_update_when_host_null(self): - with self.port() as port: + with self.port(is_admin=True) as port: data = {'port': {'admin_state_up': False}} - req = self.new_update_request('ports', data, port['port']['id']) + req = self.new_update_request('ports', data, port['port']['id'], + as_admin=True) res = self.deserialize(self.fmt, req.get_response(self.api)) self.assertEqual(port['port'][portbindings.HOST_ID], res['port'][portbindings.HOST_ID]) @@ -267,10 +249,12 @@ class PortBindingsHostTestCaseMixin(object): def test_ports_vif_host_list(self): host_arg = {portbindings.HOST_ID: self.hostname} with self.port(name='name1', + is_admin=True, arg_list=(portbindings.HOST_ID,), **host_arg) as port1,\ self.port(name='name2'),\ self.port(name='name3', + is_admin=True, arg_list=(portbindings.HOST_ID,), **host_arg) as port3: self._test_list_resources( @@ -308,23 +292,16 @@ class PortBindingsVnicTestCaseMixin(object): # Check a response of create_port self._check_response_portbindings_vnic_type(port['port']) # Check a response of get_port - ctx = context.get_admin_context() - port = self._show('ports', port_id, neutron_context=ctx)['port'] + port = self._show('ports', port_id, as_admin=True)['port'] self._check_response_portbindings_vnic_type(port) - # By default user is admin - now test non admin user - ctx = context.Context(user_id=None, - tenant_id=self._tenant_id, - is_admin=False) - non_admin_port = self._show( - 'ports', port_id, neutron_context=ctx)['port'] + non_admin_port = self._show('ports', port_id)['port'] self._check_response_portbindings_vnic_type(non_admin_port) def test_ports_vnic_type(self): vnic_arg = {portbindings.VNIC_TYPE: self.vnic_type} with self.port(name='name1', arg_list=(portbindings.VNIC_TYPE,), **vnic_arg), self.port(name='name2'): - ctx = context.get_admin_context() - ports = self._list('ports', neutron_context=ctx)['ports'] + ports = self._list('ports', as_admin=True)['ports'] self.assertEqual(2, len(ports)) for port in ports: if port['name'] == 'name1': @@ -332,11 +309,7 @@ class PortBindingsVnicTestCaseMixin(object): else: self.assertEqual(portbindings.VNIC_NORMAL, port[portbindings.VNIC_TYPE]) - # By default user is admin - now test non admin user - ctx = context.Context(user_id=None, - tenant_id=self._tenant_id, - is_admin=False) - ports = self._list('ports', neutron_context=ctx)['ports'] + ports = self._list('ports')['ports'] self.assertEqual(2, len(ports)) for non_admin_port in ports: self._check_response_portbindings_vnic_type(non_admin_port) diff --git a/neutron/tests/unit/agent/dhcp/test_agent.py b/neutron/tests/unit/agent/dhcp/test_agent.py index ecfd37b17c..7bf48f017f 100644 --- a/neutron/tests/unit/agent/dhcp/test_agent.py +++ b/neutron/tests/unit/agent/dhcp/test_agent.py @@ -37,6 +37,7 @@ from neutron.agent.linux import dhcp from neutron.agent.linux import interface from neutron.agent.linux import utils as linux_utils from neutron.agent.metadata import driver as metadata_driver +from neutron.common import _constants as common_constants from neutron.common import config as common_config from neutron.common import utils from neutron.conf.agent import common as config @@ -1929,7 +1930,7 @@ class TestDeviceManager(base.BaseTestCase): expected_ips = ['172.9.9.9/24', const.METADATA_CIDR] if ipv6_enabled: - expected_ips.append(const.METADATA_V6_CIDR) + expected_ips.append(common_constants.METADATA_V6_CIDR) expected = [mock.call.get_device_name(port)] diff --git a/neutron/tests/unit/debug/__init__.py b/neutron/tests/unit/agent/l2/extensions/metadata/__init__.py index e69de29bb2..e69de29bb2 100644 --- a/neutron/tests/unit/debug/__init__.py +++ b/neutron/tests/unit/agent/l2/extensions/metadata/__init__.py diff --git a/neutron/tests/unit/agent/l2/extensions/metadata/test_host_metadata_proxy.py b/neutron/tests/unit/agent/l2/extensions/metadata/test_host_metadata_proxy.py new file mode 100644 index 0000000000..c6a57d9846 --- /dev/null +++ b/neutron/tests/unit/agent/l2/extensions/metadata/test_host_metadata_proxy.py @@ -0,0 +1,104 @@ +# Copyright (c) 2022 China Unicom Cloud Data Co.,Ltd. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from unittest import mock + +from oslo_config import cfg + +from neutron.agent.l2.extensions.metadata import host_metadata_proxy +from neutron.agent.linux import external_process +from neutron.tests import base + + +class TestHostMedataHAProxyDaemonMonitor(base.BaseTestCase): + + def setUp(self): + super(TestHostMedataHAProxyDaemonMonitor, self).setUp() + + self.ensure_dir = mock.patch( + 'oslo_utils.fileutils.ensure_tree').start() + + self.utils_exec_p = mock.patch( + 'neutron.agent.linux.utils.execute') + self.utils_exec = self.utils_exec_p.start() + + self.utils_replace_file_p = mock.patch( + 'neutron_lib.utils.file.replace_file') + self.utils_replace_file = self.utils_replace_file_p.start() + + def test_spawn_host_metadata_haproxy(self): + cfg.CONF.set_override('metadata_proxy_shared_secret', + 'secret', group='METADATA') + conffile = '/fake/host_metadata_proxy.haproxy.conf' + pidfile = '/fake/host_metadata_proxy.pid.haproxy' + process_monitor = external_process.ProcessMonitor( + config=cfg.CONF, + resource_type='MetadataPath') + + get_conf_file_name = 'neutron.agent.linux.utils.get_conf_file_name' + get_pid_file_name = ('neutron.agent.linux.external_process.' + 'ProcessManager.get_pid_file_name') + utils_execute = 'neutron.agent.common.utils.execute' + + mock.patch(get_conf_file_name).start().return_value = conffile + mock.patch(get_pid_file_name).start().return_value = pidfile + execute = mock.patch(utils_execute).start() + + host_meta = host_metadata_proxy.HostMedataHAProxyDaemonMonitor( + process_monitor) + instance_infos = [ + {"instance_id": "uuid1", + "provider_ip": "1.1.1.1", + "project_id": "project1"}] + host_meta.config(instance_infos) + host_meta.enable() + cmd = execute.call_args[0][0] + _join = lambda *args: ' '.join(args) + cmd = _join(*cmd) + self.assertIn('haproxy', cmd) + self.assertIn(_join('-f', conffile), cmd) + self.assertIn(_join('-p', pidfile), cmd) + + def test_generate_host_metadata_haproxy_config(self): + cfg.CONF.set_override('metadata_proxy_shared_secret', + 'secret', group='METADATA') + sig = ( + "3b5421875d7ba0fc910202f5ce448d9419597e7b66f702b53335116fee60e81e") + cfg.CONF.set_override('nova_metadata_host', + '2.2.2.2', + group='METADATA') + cfg.CONF.set_override('nova_metadata_port', + '8775', + group='METADATA') + process_monitor = external_process.ProcessMonitor( + config=cfg.CONF, + resource_type='MetadataPath') + host_meta = host_metadata_proxy.HostMedataHAProxyDaemonMonitor( + process_monitor) + instance_infos = [ + host_metadata_proxy.ProxyInstance('uuid1', '1.1.1.1', 'project1')] + host_meta._generate_proxy_conf(instance_infos) + acl = "acl instance_uuid1_1.1.1.1 src 1.1.1.1" + use_acl = "use_backend backend_uuid1_1.1.1.1 if instance_uuid1_1.1.1.1" + backend = "backend backend_uuid1_1.1.1.1" + http_hd_ins_id = "http-request set-header X-Instance-ID uuid1" + http_hd_pj = "http-request set-header X-Tenant-ID project1" + http_hd_sig = ( + "http-request set-header X-Instance-ID-Signature %s" % sig) + meta_real_srv = "server metasrv 2.2.2.2:8775" + expects = [acl, use_acl, backend, http_hd_ins_id, http_hd_pj, + http_hd_sig, meta_real_srv] + for exp in expects: + self.assertIn(exp, self.utils_replace_file.call_args[0][1]) diff --git a/neutron/tests/unit/agent/linux/test_dhcp.py b/neutron/tests/unit/agent/linux/test_dhcp.py index 064461b649..98ed27d93b 100644 --- a/neutron/tests/unit/agent/linux/test_dhcp.py +++ b/neutron/tests/unit/agent/linux/test_dhcp.py @@ -33,6 +33,7 @@ import testtools from neutron.agent.linux import dhcp from neutron.agent.linux import ip_lib from neutron.cmd import runtime_checks as checks +from neutron.common import _constants as common_constants from neutron.common import utils as common_utils from neutron.conf.agent import common as config from neutron.conf.agent import dhcp as dhcp_config @@ -3295,7 +3296,7 @@ class TestDeviceManager(TestConfBase): if enable_isolated_metadata or force_metadata: expect_ips.extend([ constants.METADATA_CIDR, - constants.METADATA_V6_CIDR]) + common_constants.METADATA_V6_CIDR]) mgr.driver.init_l3.assert_called_with('ns-XXX', expect_ips, namespace='qdhcp-ns') diff --git a/neutron/tests/unit/agent/linux/test_ip_lib.py b/neutron/tests/unit/agent/linux/test_ip_lib.py index da754464c3..c488e90ddc 100644 --- a/neutron/tests/unit/agent/linux/test_ip_lib.py +++ b/neutron/tests/unit/agent/linux/test_ip_lib.py @@ -792,7 +792,7 @@ class TestIpAddrCommand(TestIPCmdBase): def test_wait_until_address_dadfailed(self): self.addr_cmd.list = mock.Mock( return_value=[{'tentative': True, 'dadfailed': True}]) - with testtools.ExpectedException(ip_lib.AddressNotReady): + with testtools.ExpectedException(ip_lib.DADFailed): self.addr_cmd.wait_until_address_ready('abcd::1234') @mock.patch.object(common_utils, 'wait_until_true') diff --git a/neutron/tests/unit/agent/linux/test_iptables_manager.py b/neutron/tests/unit/agent/linux/test_iptables_manager.py index f005bfde43..2d0743e2e1 100644 --- a/neutron/tests/unit/agent/linux/test_iptables_manager.py +++ b/neutron/tests/unit/agent/linux/test_iptables_manager.py @@ -1395,3 +1395,37 @@ class IptablesManagerNoNatTestCase(base.BaseTestCase): iptables.initialize_nat_table() self.assertIn('nat', iptables.ipv4) self.assertIn('mangle', iptables.ipv4) + + +class IptablesRandomFullyFixture(fixtures.Fixture): + def _setUp(self): + # We MUST save and restore _random_fully because it is a class + # attribute and could change state in some tests, which can cause + # the other router test cases to randomly fail due to race conditions. + self._random_fully = iptables_manager.IptablesManager._random_fully + iptables_manager.IptablesManager._random_fully = None + self.addCleanup(self._reset) + + def _reset(self): + iptables_manager.IptablesManager._random_fully = self._random_fully + + +class IptablesManagerDisableRandomFullyTestCase(base.BaseTestCase): + + def setUp(self): + super(IptablesManagerDisableRandomFullyTestCase, self).setUp() + self.useFixture(IptablesRandomFullyFixture()) + self.execute = mock.patch.object(linux_utils, "execute").start() + cfg.CONF.set_override('use_random_fully', False, "AGENT") + + def test_verify_disable_random_fully(self): + expected_calls_and_values = [ + (mock.call(['iptables', '--version'], + run_as_root=True, privsep_exec=True), + "iptables v1.6.2")] + tools.setup_mock_calls(self.execute, expected_calls_and_values) + iptables_mgrs = [iptables_manager.IptablesManager() for _ in range(3)] + # The random_full properties of all + # IptablesManager instances must return False + for ipt_mgr in iptables_mgrs: + self.assertFalse(ipt_mgr.random_fully) diff --git a/neutron/tests/unit/agent/metadata/test_driver.py b/neutron/tests/unit/agent/metadata/test_driver.py index fc59b7fee8..e3b0b8ef6e 100644 --- a/neutron/tests/unit/agent/metadata/test_driver.py +++ b/neutron/tests/unit/agent/metadata/test_driver.py @@ -25,6 +25,7 @@ from oslo_utils import uuidutils from neutron.agent.l3 import agent as l3_agent from neutron.agent.l3 import router_info from neutron.agent.linux import external_process as ep +from neutron.agent.linux import ip_lib from neutron.agent.linux import iptables_manager from neutron.agent.linux import utils as linux_utils from neutron.agent.metadata import driver as metadata_driver @@ -76,6 +77,7 @@ class TestMetadataDriverProcess(base.BaseTestCase): EUNAME = 'neutron' EGNAME = 'neutron' METADATA_DEFAULT_IP = '169.254.169.254' + METADATA_DEFAULT_IPV6 = 'fe80::a9fe:a9fe' METADATA_PORT = 8080 METADATA_SOCKET = '/socket/path' PIDFILE = 'pidfile' @@ -140,7 +142,7 @@ class TestMetadataDriverProcess(base.BaseTestCase): agent._process_updated_router(router) f.assert_not_called() - def test_spawn_metadata_proxy(self): + def _test_spawn_metadata_proxy(self, dad_failed=False): router_id = _uuid() router_ns = 'qrouter-%s' % router_id service_name = 'haproxy' @@ -165,22 +167,32 @@ class TestMetadataDriverProcess(base.BaseTestCase): 'NamespaceManager.list_all', return_value={}),\ mock.patch( 'neutron.agent.linux.ip_lib.' - 'IpAddrCommand.wait_until_address_ready') as mock_wait: + 'IpAddrCommand.wait_until_address_ready') as mock_wait,\ + mock.patch( + 'neutron.agent.linux.ip_lib.' + 'delete_ip_address') as mock_del: agent = l3_agent.L3NATAgent('localhost') + agent.process_monitor = mock.Mock() cfg_file = os.path.join( metadata_driver.HaproxyConfigurator.get_config_path( agent.conf.state_path), "%s.conf" % router_id) mock_open = self.useFixture( lib_fixtures.OpenFixture(cfg_file)).mock_open - mock_wait.return_value = True + if dad_failed: + mock_wait.side_effect = ip_lib.DADFailed( + address=self.METADATA_DEFAULT_IP, reason='DAD failed') + else: + mock_wait.return_value = True agent.metadata_driver.spawn_monitored_metadata_proxy( agent.process_monitor, router_ns, self.METADATA_PORT, agent.conf, bind_address=self.METADATA_DEFAULT_IP, - router_id=router_id) + router_id=router_id, + bind_address_v6=self.METADATA_DEFAULT_IPV6, + bind_interface='fake-if') netns_execute_args = [ service_name, @@ -188,6 +200,8 @@ class TestMetadataDriverProcess(base.BaseTestCase): log_tag = ("haproxy-" + metadata_driver.METADATA_SERVICE_NAME + "-" + router_id) + bind_v6_line = 'bind %s:%s interface %s' % ( + self.METADATA_DEFAULT_IPV6, self.METADATA_PORT, 'fake-if') cfg_contents = metadata_driver._HAPROXY_CONFIG_TEMPLATE % { 'user': self.EUNAME, 'group': self.EGNAME, @@ -200,19 +214,35 @@ class TestMetadataDriverProcess(base.BaseTestCase): 'pidfile': self.PIDFILE, 'log_level': 'debug', 'log_tag': log_tag, - 'bind_v6_line': ''} - - mock_open.assert_has_calls([ - mock.call(cfg_file, 'w'), - mock.call().write(cfg_contents)], - any_order=True) - - env = {ep.PROCESS_TAG: service_name + '-' + router_id} - ip_mock.assert_has_calls([ - mock.call(namespace=router_ns), - mock.call().netns.execute(netns_execute_args, addl_env=env, - run_as_root=True) - ]) + 'bind_v6_line': bind_v6_line} + + if dad_failed: + agent.process_monitor.register.assert_not_called() + mock_del.assert_called_once_with(self.METADATA_DEFAULT_IPV6, + 'fake-if', + namespace=router_ns) + else: + mock_open.assert_has_calls([ + mock.call(cfg_file, 'w'), + mock.call().write(cfg_contents)], any_order=True) + + env = {ep.PROCESS_TAG: service_name + '-' + router_id} + ip_mock.assert_has_calls([ + mock.call(namespace=router_ns), + mock.call().netns.execute(netns_execute_args, addl_env=env, + run_as_root=True) + ]) + + agent.process_monitor.register.assert_called_once_with( + router_id, metadata_driver.METADATA_SERVICE_NAME, + mock.ANY) + mock_del.assert_not_called() + + def test_spawn_metadata_proxy(self): + self._test_spawn_metadata_proxy() + + def test_spawn_metadata_proxy_dad_failed(self): + self._test_spawn_metadata_proxy(dad_failed=True) def test_create_config_file_wrong_user(self): with mock.patch('pwd.getpwnam', side_effect=KeyError): diff --git a/neutron/tests/unit/api/test_extensions.py b/neutron/tests/unit/api/test_extensions.py index 7e15bc4077..14155f1b02 100644 --- a/neutron/tests/unit/api/test_extensions.py +++ b/neutron/tests/unit/api/test_extensions.py @@ -17,6 +17,7 @@ import copy from unittest import mock import fixtures +from neutron_lib import context from neutron_lib import exceptions from neutron_lib.plugins import constants as lib_const from neutron_lib.plugins import directory @@ -1045,6 +1046,8 @@ class ExtensionExtendedAttributeTestCase(base.BaseTestCase): req = testlib_api.create_request( path, body, content_type, method, query_string=params) + req.environ['neutron.context'] = context.Context( + '', self._tenant_id, roles=['member', 'reader']) res = req.get_response(self._api) if res.status_code >= 400: raise webexc.HTTPClientError(detail=res.body, code=res.status_code) diff --git a/neutron/tests/unit/api/v2/test_base.py b/neutron/tests/unit/api/v2/test_base.py index f0cb1f1a26..2e2a32e8e0 100644 --- a/neutron/tests/unit/api/v2/test_base.py +++ b/neutron/tests/unit/api/v2/test_base.py @@ -74,6 +74,14 @@ def _get_path(resource, id=None, action=None, return path +def _get_neutron_env(tenant_id=None, as_admin=False): + tenant_id = tenant_id or _uuid() + roles = ['member', 'reader'] + if as_admin: + roles.append('admin') + return {'neutron.context': context.Context('', tenant_id, roles=roles)} + + class APIv2TestBase(base.BaseTestCase): def setUp(self): super(APIv2TestBase, self).setUp() @@ -98,6 +106,8 @@ class APIv2TestBase(base.BaseTestCase): api = router.APIRouter() self.api = webtest.TestApp(api) + self._tenant_id = "api-test-tenant" + quota.QUOTAS._driver = None cfg.CONF.set_override('quota_driver', quota_conf.QUOTA_DB_DRIVER, group='QUOTAS') @@ -105,6 +115,27 @@ class APIv2TestBase(base.BaseTestCase): # APIRouter initialization resets policy module, re-initializing it policy.init() + def _post_request(self, path, initial_input, expect_errors=None, + req_tenant_id=None, as_admin=False): + req_tenant_id = req_tenant_id or self._tenant_id + return self.api.post_json( + path, initial_input, expect_errors=expect_errors, + extra_environ=_get_neutron_env(req_tenant_id, as_admin)) + + def _put_request(self, path, initial_input, expect_errors=None, + req_tenant_id=None, as_admin=False): + req_tenant_id = req_tenant_id or self._tenant_id + return self.api.put_json( + path, initial_input, expect_errors=expect_errors, + extra_environ=_get_neutron_env(req_tenant_id, as_admin)) + + def _delete_request(self, path, expect_errors=None, + req_tenant_id=None, as_admin=False): + req_tenant_id = req_tenant_id or self._tenant_id + return self.api.delete_json( + path, expect_errors=expect_errors, + extra_environ=_get_neutron_env(req_tenant_id, as_admin)) + class _ArgMatcher(object): """An adapter to assist mock assertions, used to custom compare.""" @@ -512,17 +543,16 @@ class JSONV2TestCase(APIv2TestBase, testlib_api.WebTestCase): def _test_list(self, req_tenant_id, real_tenant_id): env = {} if req_tenant_id: - env = {'neutron.context': context.Context('', req_tenant_id)} + env = _get_neutron_env(req_tenant_id) input_dict = {'id': uuidutils.generate_uuid(), 'name': 'net1', 'admin_state_up': True, 'status': "ACTIVE", - 'tenant_id': real_tenant_id, + 'project_id': real_tenant_id, 'shared': False, 'subnets': []} - return_value = [input_dict] instance = self.plugin.return_value - instance.get_networks.return_value = return_value + instance.get_networks.return_value = [input_dict] res = self.api.get(_get_path('networks', fmt=self.fmt), extra_environ=env) @@ -789,7 +819,7 @@ class JSONV2TestCase(APIv2TestBase, testlib_api.WebTestCase): def test_create_with_keystone_env(self): tenant_id = _uuid() net_id = _uuid() - env = {'neutron.context': context.Context('', tenant_id)} + env = _get_neutron_env(tenant_id) # tenant_id should be fetched from env initial_input = {'network': {'name': 'net1'}} full_input = {'network': {'admin_state_up': True, @@ -947,8 +977,9 @@ class JSONV2TestCase(APIv2TestBase, testlib_api.WebTestCase): def test_create_return_extra_attr(self): net_id = _uuid() + project_id = _uuid() data = {'network': {'name': 'net1', 'admin_state_up': True, - 'tenant_id': _uuid()}} + 'tenant_id': project_id}} return_value = {'subnets': [], 'status': "ACTIVE", 'id': net_id, 'v2attrs:something': "123"} return_value.update(data['network'].copy()) @@ -959,7 +990,8 @@ class JSONV2TestCase(APIv2TestBase, testlib_api.WebTestCase): res = self.api.post(_get_path('networks', fmt=self.fmt), self.serialize(data), - content_type='application/' + self.fmt) + content_type='application/' + self.fmt, + extra_environ=_get_neutron_env(project_id)) self.assertEqual(exc.HTTPCreated.code, res.status_int) res = self.deserialize(res) self.assertIn('network', res) @@ -969,23 +1001,25 @@ class JSONV2TestCase(APIv2TestBase, testlib_api.WebTestCase): self.assertNotIn('v2attrs:something', net) def test_fields(self): + project_id = _uuid() return_value = {'name': 'net1', 'admin_state_up': True, - 'subnets': []} + 'project_id': project_id, 'subnets': []} instance = self.plugin.return_value instance.get_network.return_value = return_value self.api.get(_get_path('networks', id=uuidutils.generate_uuid(), - fmt=self.fmt)) + fmt=self.fmt), + extra_environ=_get_neutron_env(project_id)) def _test_delete(self, req_tenant_id, real_tenant_id, expected_code, expect_errors=False): env = {} if req_tenant_id: - env = {'neutron.context': context.Context('', req_tenant_id)} + env = _get_neutron_env(req_tenant_id) instance = self.plugin.return_value - instance.get_network.return_value = {'tenant_id': real_tenant_id, + instance.get_network.return_value = {'project_id': real_tenant_id, 'shared': False} instance.delete_network.return_value = None @@ -1010,15 +1044,12 @@ class JSONV2TestCase(APIv2TestBase, testlib_api.WebTestCase): def _test_get(self, req_tenant_id, real_tenant_id, expected_code, expect_errors=False): + shared = req_tenant_id and req_tenant_id.endswith('another') env = {} - shared = False if req_tenant_id: - env = {'neutron.context': context.Context('', req_tenant_id)} - if req_tenant_id.endswith('another'): - shared = True - env['neutron.context'].roles = ['tenant_admin'] + env = _get_neutron_env(req_tenant_id) - data = {'tenant_id': real_tenant_id, 'shared': shared} + data = {'project_id': real_tenant_id, 'shared': shared} instance = self.plugin.return_value instance.get_network.return_value = data @@ -1060,14 +1091,14 @@ class JSONV2TestCase(APIv2TestBase, testlib_api.WebTestCase): expect_errors=False): env = {} if req_tenant_id: - env = {'neutron.context': context.Context('', req_tenant_id)} + env = _get_neutron_env(req_tenant_id) # leave out 'name' field intentionally data = {'network': {'admin_state_up': True}} return_value = {'subnets': []} return_value.update(data['network'].copy()) instance = self.plugin.return_value - instance.get_network.return_value = {'tenant_id': real_tenant_id, + instance.get_network.return_value = {'project_id': real_tenant_id, 'shared': False} instance.update_network.return_value = return_value @@ -1308,26 +1339,31 @@ class NotificationTest(APIv2TestBase): group='QUOTAS') def _resource_op_notifier(self, opname, resource, expected_errors=False): - initial_input = {resource: {'name': 'myname'}} + tenant_id = _uuid() + network_obj = {'name': 'myname', + 'project_id': tenant_id} + initial_input = {resource: network_obj} instance = self.plugin.return_value - instance.get_networks.return_value = initial_input + instance.get_network.return_value = network_obj instance.get_networks_count.return_value = 0 expected_code = exc.HTTPCreated.code if opname == 'create': - initial_input[resource]['tenant_id'] = _uuid() - res = self.api.post_json( + res = self._post_request( _get_path('networks'), - initial_input, expect_errors=expected_errors) + initial_input, expect_errors=expected_errors, + req_tenant_id=tenant_id) if opname == 'update': - res = self.api.put_json( - _get_path('networks', id=_uuid()), - initial_input, expect_errors=expected_errors) + op_input = {resource: {'name': 'myname'}} + res = self._put_request( + _get_path('networks', id=tenant_id), + op_input, expect_errors=expected_errors, + req_tenant_id=tenant_id) expected_code = exc.HTTPOk.code if opname == 'delete': - initial_input[resource]['tenant_id'] = _uuid() - res = self.api.delete( - _get_path('networks', id=_uuid()), - expect_errors=expected_errors) + res = self._delete_request( + _get_path('networks', id=tenant_id), + expect_errors=expected_errors, + req_tenant_id=tenant_id) expected_code = exc.HTTPNoContent.code expected_events = ('.'.join([resource, opname, "start"]), @@ -1472,7 +1508,9 @@ class ExtensionTestCase(base.BaseTestCase): instance.create_network.return_value = return_value instance.get_networks_count.return_value = 0 - res = self.api.post_json(_get_path('networks'), initial_input) + res = self.api.post_json( + _get_path('networks'), initial_input, + extra_environ=_get_neutron_env(tenant_id)) instance.create_network.assert_called_with(mock.ANY, network=data) diff --git a/neutron/tests/unit/conf/policies/test_availability_zone.py b/neutron/tests/unit/conf/policies/test_availability_zone.py index ad797da9b4..85d9679121 100644 --- a/neutron/tests/unit/conf/policies/test_availability_zone.py +++ b/neutron/tests/unit/conf/policies/test_availability_zone.py @@ -70,12 +70,6 @@ class ProjectMemberTests(AdminTests): super(ProjectMemberTests, self).setUp() self.context = self.project_member_ctx - def test_get_availability_zone(self): - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, "get_availability_zone", self.target) - class ProjectReaderTests(ProjectMemberTests): diff --git a/neutron/tests/unit/conf/policies/test_floatingip_port_forwarding.py b/neutron/tests/unit/conf/policies/test_floatingip_port_forwarding.py index d72d61870e..ab1446e98d 100644 --- a/neutron/tests/unit/conf/policies/test_floatingip_port_forwarding.py +++ b/neutron/tests/unit/conf/policies/test_floatingip_port_forwarding.py @@ -28,16 +28,19 @@ class FloatingipPortForwardingAPITestCase(base.PolicyBaseTestCase): super(FloatingipPortForwardingAPITestCase, self).setUp() self.fip = { 'id': uuidutils.generate_uuid(), + 'tenant_id': self.project_id, 'project_id': self.project_id} + self.alt_fip = { + 'id': uuidutils.generate_uuid(), + 'tenant_id': self.alt_project_id, + 'project_id': self.alt_project_id} self.target = { - 'project_id': self.project_id, 'floatingip_id': self.fip['id'], 'ext_parent_floatingip_id': self.fip['id']} self.alt_target = { - 'project_id': self.alt_project_id, - 'floatingip_id': self.fip['id'], - 'ext_parent_floatingip_id': self.fip['id']} + 'floatingip_id': self.alt_fip['id'], + 'ext_parent_floatingip_id': self.alt_fip['id']} self.plugin_mock = mock.Mock() self.plugin_mock.get_floatingip.return_value = self.fip @@ -53,52 +56,68 @@ class SystemAdminTests(FloatingipPortForwardingAPITestCase): self.context = self.system_admin_ctx def test_create_fip_pf(self): - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'create_floatingip_port_forwarding', - self.target) - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'create_floatingip_port_forwarding', - self.alt_target) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.fip): + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'create_floatingip_port_forwarding', + self.target) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.alt_fip): + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'create_floatingip_port_forwarding', + self.alt_target) def test_get_fip_pf(self): - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'get_floatingip_port_forwarding', - self.target) - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'get_floatingip_port_forwarding', - self.alt_target) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.fip): + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'get_floatingip_port_forwarding', + self.target) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.alt_fip): + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'get_floatingip_port_forwarding', + self.alt_target) def test_update_fip_pf(self): - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'update_floatingip_port_forwarding', - self.target) - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'update_floatingip_port_forwarding', - self.alt_target) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.fip): + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'update_floatingip_port_forwarding', + self.target) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.alt_fip): + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'update_floatingip_port_forwarding', + self.alt_target) def test_delete_fip_pf(self): - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'delete_floatingip_port_forwarding', - self.target) - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'delete_floatingip_port_forwarding', - self.alt_target) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.fip): + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'delete_floatingip_port_forwarding', + self.target) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.alt_fip): + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'delete_floatingip_port_forwarding', + self.alt_target) class SystemMemberTests(SystemAdminTests): @@ -122,44 +141,60 @@ class AdminTests(FloatingipPortForwardingAPITestCase): self.context = self.project_admin_ctx def test_create_fip_pf(self): - self.assertTrue( - policy.enforce(self.context, - 'create_floatingip_port_forwarding', - self.target)) - self.assertTrue( - policy.enforce(self.context, - 'create_floatingip_port_forwarding', - self.alt_target)) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.fip): + self.assertTrue( + policy.enforce(self.context, + 'create_floatingip_port_forwarding', + self.target)) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.alt_fip): + self.assertTrue( + policy.enforce(self.context, + 'create_floatingip_port_forwarding', + self.alt_target)) def test_get_fip_pf(self): - self.assertTrue( - policy.enforce(self.context, - 'get_floatingip_port_forwarding', - self.target)) - self.assertTrue( - policy.enforce(self.context, - 'get_floatingip_port_forwarding', - self.alt_target)) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.fip): + self.assertTrue( + policy.enforce(self.context, + 'get_floatingip_port_forwarding', + self.target)) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.alt_fip): + self.assertTrue( + policy.enforce(self.context, + 'get_floatingip_port_forwarding', + self.alt_target)) def test_update_fip_pf(self): - self.assertTrue( - policy.enforce(self.context, - 'update_floatingip_port_forwarding', - self.target)) - self.assertTrue( - policy.enforce(self.context, - 'update_floatingip_port_forwarding', - self.alt_target)) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.fip): + self.assertTrue( + policy.enforce(self.context, + 'update_floatingip_port_forwarding', + self.target)) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.alt_fip): + self.assertTrue( + policy.enforce(self.context, + 'update_floatingip_port_forwarding', + self.alt_target)) def test_delete_fip_pf(self): - self.assertTrue( - policy.enforce(self.context, - 'delete_floatingip_port_forwarding', - self.target)) - self.assertTrue( - policy.enforce(self.context, - 'delete_floatingip_port_forwarding', - self.alt_target)) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.fip): + self.assertTrue( + policy.enforce(self.context, + 'delete_floatingip_port_forwarding', + self.target)) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.alt_fip): + self.assertTrue( + policy.enforce(self.context, + 'delete_floatingip_port_forwarding', + self.alt_target)) class ProjectMemberTests(AdminTests): @@ -169,48 +204,64 @@ class ProjectMemberTests(AdminTests): self.context = self.project_member_ctx def test_create_fip_pf(self): - self.assertTrue( - policy.enforce(self.context, - 'create_floatingip_port_forwarding', - self.target)) - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'create_floatingip_port_forwarding', - self.alt_target) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.fip): + self.assertTrue( + policy.enforce(self.context, + 'create_floatingip_port_forwarding', + self.target)) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.alt_fip): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'create_floatingip_port_forwarding', + self.alt_target) def test_get_fip_pf(self): - self.assertTrue( - policy.enforce(self.context, - 'get_floatingip_port_forwarding', - self.target)) - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'get_floatingip_port_forwarding', - self.alt_target) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.fip): + self.assertTrue( + policy.enforce(self.context, + 'get_floatingip_port_forwarding', + self.target)) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.alt_fip): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'get_floatingip_port_forwarding', + self.alt_target) def test_update_fip_pf(self): - self.assertTrue( - policy.enforce(self.context, - 'update_floatingip_port_forwarding', - self.target)) - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'update_floatingip_port_forwarding', - self.alt_target) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.fip): + self.assertTrue( + policy.enforce(self.context, + 'update_floatingip_port_forwarding', + self.target)) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.alt_fip): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'update_floatingip_port_forwarding', + self.alt_target) def test_delete_fip_pf(self): - self.assertTrue( - policy.enforce(self.context, - 'delete_floatingip_port_forwarding', - self.target)) - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'delete_floatingip_port_forwarding', - self.alt_target) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.fip): + self.assertTrue( + policy.enforce(self.context, + 'delete_floatingip_port_forwarding', + self.target)) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.alt_fip): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'delete_floatingip_port_forwarding', + self.alt_target) class ProjectReaderTests(ProjectMemberTests): @@ -220,37 +271,49 @@ class ProjectReaderTests(ProjectMemberTests): self.context = self.project_reader_ctx def test_create_fip_pf(self): - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'create_floatingip_port_forwarding', - self.target) - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'create_floatingip_port_forwarding', - self.alt_target) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.fip): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'create_floatingip_port_forwarding', + self.target) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.alt_fip): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'create_floatingip_port_forwarding', + self.alt_target) def test_update_fip_pf(self): - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'update_floatingip_port_forwarding', - self.target) - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'update_floatingip_port_forwarding', - self.alt_target) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.fip): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'update_floatingip_port_forwarding', + self.target) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.alt_fip): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'update_floatingip_port_forwarding', + self.alt_target) def test_delete_fip_pf(self): - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'delete_floatingip_port_forwarding', - self.target) - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'delete_floatingip_port_forwarding', - self.alt_target) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.fip): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'delete_floatingip_port_forwarding', + self.target) + with mock.patch.object(self.plugin_mock, 'get_floatingip', + return_value=self.alt_fip): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'delete_floatingip_port_forwarding', + self.alt_target) diff --git a/neutron/tests/unit/conf/policies/test_port.py b/neutron/tests/unit/conf/policies/test_port.py index c50d3feb10..8248960abb 100644 --- a/neutron/tests/unit/conf/policies/test_port.py +++ b/neutron/tests/unit/conf/policies/test_port.py @@ -532,6 +532,16 @@ class AdminTests(PortAPITestCase): 'create_port:allowed_address_pairs:ip_address', self.alt_target)) + def test_create_port_with_hints(self): + self.assertTrue( + policy.enforce(self.context, + 'create_port:hints', + self.target)) + self.assertTrue( + policy.enforce(self.context, + 'create_port:hints', + self.alt_target)) + def test_get_port(self): self.assertTrue( policy.enforce(self.context, 'get_port', self.target)) @@ -578,6 +588,14 @@ class AdminTests(PortAPITestCase): policy.enforce( self.context, 'get_port:resource_request', self.alt_target)) + def test_get_port_hints(self): + self.assertTrue( + policy.enforce( + self.context, 'get_port:hints', self.target)) + self.assertTrue( + policy.enforce( + self.context, 'get_port:hints', self.alt_target)) + def test_update_port(self): self.assertTrue( policy.enforce(self.context, 'update_port', self.target)) @@ -701,6 +719,16 @@ class AdminTests(PortAPITestCase): 'update_port:data_plane_status', self.alt_target)) + def test_update_port_hints(self): + self.assertTrue( + policy.enforce(self.context, + 'update_port:hints', + self.target)) + self.assertTrue( + policy.enforce(self.context, + 'update_port:hints', + self.alt_target)) + def test_delete_port(self): self.assertTrue( policy.enforce(self.context, 'delete_port', self.target)) @@ -850,6 +878,18 @@ class ProjectMemberTests(AdminTests): self.context, 'create_port:allowed_address_pairs:ip_address', self.alt_target) + def test_create_port_with_hints(self): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'create_port:hints', + self.target) + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'create_port:hints', + self.alt_target) + def test_get_port(self): self.assertTrue( policy.enforce(self.context, 'get_port', self.target)) @@ -907,6 +947,16 @@ class ProjectMemberTests(AdminTests): policy.enforce, self.context, 'get_port:resource_request', self.alt_target) + def test_get_port_hints(self): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, self.context, 'get_port:hints', + self.target) + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, self.context, 'get_port:hints', + self.alt_target) + def test_update_port(self): self.assertTrue( policy.enforce(self.context, 'update_port', self.target)) @@ -1053,6 +1103,16 @@ class ProjectMemberTests(AdminTests): policy.enforce, self.context, 'update_port:data_plane_status', self.alt_target) + def test_update_port_hints(self): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'update_port:hints', self.target) + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'update_port:hints', self.alt_target) + def test_delete_port(self): self.assertTrue( policy.enforce(self.context, 'delete_port', self.target)) diff --git a/neutron/tests/unit/conf/policies/test_qos.py b/neutron/tests/unit/conf/policies/test_qos.py index 8b468484da..ff655b298e 100644 --- a/neutron/tests/unit/conf/policies/test_qos.py +++ b/neutron/tests/unit/conf/policies/test_qos.py @@ -210,12 +210,6 @@ class ProjectMemberQosRuleTypeTests(AdminQosRuleTypeTests): super(ProjectMemberQosRuleTypeTests, self).setUp() self.context = self.project_member_ctx - def test_get_rule_type(self): - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'get_rule_type', self.target) - class ProjectReaderQosRuleTypeTests(ProjectMemberQosRuleTypeTests): @@ -230,18 +224,20 @@ class QosRulesAPITestCase(base.PolicyBaseTestCase): super(QosRulesAPITestCase, self).setUp() self.qos_policy = { 'id': uuidutils.generate_uuid(), + 'tenant_id': self.project_id, 'project_id': self.project_id} + self.alt_qos_policy = { + 'id': uuidutils.generate_uuid(), + 'tenant_id': self.alt_project_id, + 'project_id': self.alt_project_id} self.target = { - 'project_id': self.project_id, 'policy_id': self.qos_policy['id'], 'ext_parent_policy_id': self.qos_policy['id']} self.alt_target = { - 'project_id': self.alt_project_id, - 'policy_id': self.qos_policy['id'], - 'ext_parent_policy_id': self.qos_policy['id']} + 'policy_id': self.alt_qos_policy['id'], + 'ext_parent_policy_id': self.alt_qos_policy['id']} self.plugin_mock = mock.Mock() - self.plugin_mock.get_qos_policy.return_value = self.qos_policy mock.patch( 'neutron_lib.plugins.directory.get_plugin', return_value=self.plugin_mock).start() @@ -254,28 +250,33 @@ class SystemAdminQosBandwidthLimitRuleTests(QosRulesAPITestCase): self.context = self.system_admin_ctx def test_get_policy_bandwidth_limit_rule(self): - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'get_policy_bandwidth_limit_rule', - self.target) - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'get_policy_bandwidth_limit_rule', - self.alt_target) - - # And the same for aliases - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'get_alias_bandwidth_limit_rule', - self.target) - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'get_alias_bandwidth_limit_rule', - self.alt_target) + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.qos_policy): + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'get_policy_bandwidth_limit_rule', + self.target) + # And the same for aliases + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'get_alias_bandwidth_limit_rule', + self.target) + + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.alt_qos_policy): + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'get_policy_bandwidth_limit_rule', + self.alt_target) + # And the same for aliases + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'get_alias_bandwidth_limit_rule', + self.alt_target) def test_create_policy_bandwidth_limit_rule(self): self.assertRaises( @@ -361,24 +362,29 @@ class AdminQosBandwidthLimitRuleTests(QosRulesAPITestCase): self.context = self.project_admin_ctx def test_get_policy_bandwidth_limit_rule(self): - self.assertTrue( - policy.enforce(self.context, - 'get_policy_bandwidth_limit_rule', - self.target)) - self.assertTrue( - policy.enforce(self.context, - 'get_policy_bandwidth_limit_rule', - self.alt_target)) - - # And the same for aliases - self.assertTrue( - policy.enforce(self.context, - 'get_alias_bandwidth_limit_rule', - self.target)) - self.assertTrue( - policy.enforce(self.context, - 'get_alias_bandwidth_limit_rule', - self.alt_target)) + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.qos_policy): + self.assertTrue( + policy.enforce(self.context, + 'get_policy_bandwidth_limit_rule', + self.target)) + # And the same for aliases + self.assertTrue( + policy.enforce(self.context, + 'get_alias_bandwidth_limit_rule', + self.target)) + + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.alt_qos_policy): + self.assertTrue( + policy.enforce(self.context, + 'get_policy_bandwidth_limit_rule', + self.alt_target)) + # And the same for aliases + self.assertTrue( + policy.enforce(self.context, + 'get_alias_bandwidth_limit_rule', + self.alt_target)) def test_create_policy_bandwidth_limit_rule(self): self.assertTrue( @@ -439,26 +445,32 @@ class ProjectMemberQosBandwidthLimitRuleTests( self.context = self.project_member_ctx def test_get_policy_bandwidth_limit_rule(self): - self.assertTrue( - policy.enforce(self.context, - 'get_policy_bandwidth_limit_rule', - self.target)) - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'get_policy_bandwidth_limit_rule', - self.alt_target) - - # And the same for aliases - self.assertTrue( - policy.enforce(self.context, - 'get_alias_bandwidth_limit_rule', - self.target)) - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'get_alias_bandwidth_limit_rule', - self.alt_target) + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.qos_policy): + self.assertTrue( + policy.enforce(self.context, + 'get_policy_bandwidth_limit_rule', + self.target)) + # And the same for aliases + self.assertTrue( + policy.enforce(self.context, + 'get_alias_bandwidth_limit_rule', + self.target)) + + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.alt_qos_policy): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'get_policy_bandwidth_limit_rule', + self.alt_target) + + # And the same for aliases + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'get_alias_bandwidth_limit_rule', + self.alt_target) def test_create_policy_bandwidth_limit_rule(self): self.assertRaises( @@ -591,14 +603,19 @@ class AdminQosPacketRateLimitRuleTests(QosRulesAPITestCase): self.context = self.project_admin_ctx def test_get_policy_packet_rate_limit_rule(self): - self.assertTrue( - policy.enforce(self.context, - 'get_policy_packet_rate_limit_rule', - self.target)) - self.assertTrue( - policy.enforce(self.context, - 'get_policy_packet_rate_limit_rule', - self.alt_target)) + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.qos_policy): + self.assertTrue( + policy.enforce(self.context, + 'get_policy_packet_rate_limit_rule', + self.target)) + + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.alt_qos_policy): + self.assertTrue( + policy.enforce(self.context, + 'get_policy_packet_rate_limit_rule', + self.alt_target)) def test_create_policy_packet_rate_limit_rule(self): self.assertTrue( @@ -639,15 +656,20 @@ class ProjectMemberQosPacketRateLimitRuleTests( self.context = self.project_member_ctx def test_get_policy_packet_rate_limit_rule(self): - self.assertTrue( - policy.enforce(self.context, - 'get_policy_packet_rate_limit_rule', - self.target)) - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'get_policy_packet_rate_limit_rule', - self.alt_target) + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.qos_policy): + self.assertTrue( + policy.enforce(self.context, + 'get_policy_packet_rate_limit_rule', + self.target)) + + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.alt_qos_policy): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'get_policy_packet_rate_limit_rule', + self.alt_target) def test_create_policy_packet_rate_limit_rule(self): self.assertRaises( @@ -701,28 +723,35 @@ class SystemAdminQosDSCPMarkingRuleTests(QosRulesAPITestCase): self.context = self.system_admin_ctx def test_get_policy_dscp_marking_rule(self): - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'get_policy_dscp_marking_rule', - self.target) - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'get_policy_dscp_marking_rule', - self.alt_target) - - # And the same for aliases - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'get_alias_dscp_marking_rule', - self.target) - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'get_alias_dscp_marking_rule', - self.alt_target) + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.qos_policy): + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'get_policy_dscp_marking_rule', + self.target) + + # And the same for aliases + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'get_alias_dscp_marking_rule', + self.target) + + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.alt_qos_policy): + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'get_policy_dscp_marking_rule', + self.alt_target) + + # And the same for aliases + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'get_alias_dscp_marking_rule', + self.alt_target) def test_create_policy_dscp_marking_rule(self): self.assertRaises( @@ -806,24 +835,29 @@ class AdminQosDSCPMarkingRuleTests(QosRulesAPITestCase): self.context = self.project_admin_ctx def test_get_policy_dscp_marking_rule(self): - self.assertTrue( - policy.enforce(self.context, - 'get_policy_dscp_marking_rule', - self.target)) - self.assertTrue( - policy.enforce(self.context, - 'get_policy_dscp_marking_rule', - self.alt_target)) - - # And the same for aliases - self.assertTrue( - policy.enforce(self.context, - 'get_alias_dscp_marking_rule', - self.target)) - self.assertTrue( - policy.enforce(self.context, - 'get_alias_dscp_marking_rule', - self.alt_target)) + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.qos_policy): + self.assertTrue( + policy.enforce(self.context, + 'get_policy_dscp_marking_rule', + self.target)) + # And the same for aliases + self.assertTrue( + policy.enforce(self.context, + 'get_alias_dscp_marking_rule', + self.target)) + + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.alt_qos_policy): + self.assertTrue( + policy.enforce(self.context, + 'get_policy_dscp_marking_rule', + self.alt_target)) + # And the same for aliases + self.assertTrue( + policy.enforce(self.context, + 'get_alias_dscp_marking_rule', + self.alt_target)) def test_create_policy_dscp_marking_rule(self): self.assertTrue( @@ -884,26 +918,31 @@ class ProjectMemberQosDSCPMarkingRuleTests( self.context = self.project_member_ctx def test_get_policy_dscp_marking_rule(self): - self.assertTrue( - policy.enforce(self.context, - 'get_policy_dscp_marking_rule', - self.target)) - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'get_policy_dscp_marking_rule', - self.alt_target) - - # And the same for aliases - self.assertTrue( - policy.enforce(self.context, - 'get_alias_dscp_marking_rule', - self.target)) - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'get_alias_dscp_marking_rule', - self.alt_target) + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.qos_policy): + self.assertTrue( + policy.enforce(self.context, + 'get_policy_dscp_marking_rule', + self.target)) + # And the same for aliases + self.assertTrue( + policy.enforce(self.context, + 'get_alias_dscp_marking_rule', + self.target)) + + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.alt_qos_policy): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'get_policy_dscp_marking_rule', + self.alt_target) + # And the same for aliases + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'get_alias_dscp_marking_rule', + self.alt_target) def test_create_policy_dscp_marking_rule(self): self.assertRaises( @@ -981,28 +1020,33 @@ class SystemAdminQosMinimumBandwidthRuleTests(QosRulesAPITestCase): self.context = self.system_admin_ctx def test_get_policy_minimum_bandwidth_rule(self): - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'get_policy_minimum_bandwidth_rule', - self.target) - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'get_policy_minimum_bandwidth_rule', - self.alt_target) + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.qos_policy): + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'get_policy_minimum_bandwidth_rule', + self.target) + # And the same for aliases + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'get_alias_minimum_bandwidth_rule', + self.target) - # And the same for aliases - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'get_alias_minimum_bandwidth_rule', - self.target) - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'get_alias_minimum_bandwidth_rule', - self.alt_target) + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.alt_qos_policy): + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'get_policy_minimum_bandwidth_rule', + self.alt_target) + # And the same for aliases + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'get_alias_minimum_bandwidth_rule', + self.alt_target) def test_create_policy_minimum_bandwidth_rule(self): self.assertRaises( @@ -1088,24 +1132,29 @@ class AdminQosMinimumBandwidthRuleTests(QosRulesAPITestCase): self.context = self.project_admin_ctx def test_get_policy_minimum_bandwidth_rule(self): - self.assertTrue( - policy.enforce( - self.context, 'get_policy_minimum_bandwidth_rule', - self.target)) - self.assertTrue( - policy.enforce( - self.context, 'get_policy_minimum_bandwidth_rule', - self.alt_target)) - - # And the same for aliases - self.assertTrue( - policy.enforce( - self.context, 'get_alias_minimum_bandwidth_rule', - self.target)) - self.assertTrue( - policy.enforce( - self.context, 'get_alias_minimum_bandwidth_rule', - self.alt_target)) + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.qos_policy): + self.assertTrue( + policy.enforce( + self.context, 'get_policy_minimum_bandwidth_rule', + self.target)) + # And the same for aliases + self.assertTrue( + policy.enforce( + self.context, 'get_alias_minimum_bandwidth_rule', + self.target)) + + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.alt_qos_policy): + self.assertTrue( + policy.enforce( + self.context, 'get_policy_minimum_bandwidth_rule', + self.alt_target)) + # And the same for aliases + self.assertTrue( + policy.enforce( + self.context, 'get_alias_minimum_bandwidth_rule', + self.alt_target)) def test_create_policy_minimum_bandwidth_rule(self): self.assertTrue( @@ -1166,26 +1215,31 @@ class ProjectMemberQosMinimumBandwidthRuleTests( self.context = self.project_member_ctx def test_get_policy_minimum_bandwidth_rule(self): - self.assertTrue( - policy.enforce( + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.qos_policy): + self.assertTrue( + policy.enforce( + self.context, 'get_policy_minimum_bandwidth_rule', + self.target)) + # And the same for aliases + self.assertTrue( + policy.enforce( + self.context, 'get_alias_minimum_bandwidth_rule', + self.target)) + + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.alt_qos_policy): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, self.context, 'get_policy_minimum_bandwidth_rule', - self.target)) - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'get_policy_minimum_bandwidth_rule', - self.alt_target) - - # And the same for aliases - self.assertTrue( - policy.enforce( + self.alt_target) + # And the same for aliases + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, self.context, 'get_alias_minimum_bandwidth_rule', - self.target)) - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'get_alias_minimum_bandwidth_rule', - self.alt_target) + self.alt_target) def test_create_policy_minimum_bandwidth_rule(self): self.assertRaises( @@ -1263,28 +1317,33 @@ class SystemAdminQosMinimumPacketRateRuleTests(QosRulesAPITestCase): self.context = self.system_admin_ctx def test_get_policy_minimum_packet_rate_rule(self): - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'get_policy_minimum_packet_rate_rule', - self.target) - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'get_policy_minimum_packet_rate_rule', - self.alt_target) - - # And the same for aliases - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'get_alias_minimum_packet_rate_rule', - self.target) - self.assertRaises( - base_policy.InvalidScope, - policy.enforce, - self.context, 'get_alias_minimum_packet_rate_rule', - self.alt_target) + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.qos_policy): + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'get_policy_minimum_packet_rate_rule', + self.target) + # And the same for aliases + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'get_alias_minimum_packet_rate_rule', + self.target) + + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.alt_qos_policy): + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'get_policy_minimum_packet_rate_rule', + self.alt_target) + # And the same for aliases + self.assertRaises( + base_policy.InvalidScope, + policy.enforce, + self.context, 'get_alias_minimum_packet_rate_rule', + self.alt_target) def test_create_policy_minimum_packet_rate_rule(self): self.assertRaises( @@ -1370,24 +1429,29 @@ class AdminQosMinimumPacketRateRuleTests(QosRulesAPITestCase): self.context = self.project_admin_ctx def test_get_policy_minimum_packet_rate_rule(self): - self.assertTrue( - policy.enforce(self.context, - 'get_policy_minimum_packet_rate_rule', - self.target)) - self.assertTrue( - policy.enforce(self.context, - 'get_policy_minimum_packet_rate_rule', - self.alt_target)) - - # And the same for aliases - self.assertTrue( - policy.enforce(self.context, - 'get_alias_minimum_packet_rate_rule', - self.target)) - self.assertTrue( - policy.enforce(self.context, - 'get_alias_minimum_packet_rate_rule', - self.alt_target)) + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.qos_policy): + self.assertTrue( + policy.enforce(self.context, + 'get_policy_minimum_packet_rate_rule', + self.target)) + # And the same for aliases + self.assertTrue( + policy.enforce(self.context, + 'get_alias_minimum_packet_rate_rule', + self.target)) + + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.alt_qos_policy): + self.assertTrue( + policy.enforce(self.context, + 'get_policy_minimum_packet_rate_rule', + self.alt_target)) + # And the same for aliases + self.assertTrue( + policy.enforce(self.context, + 'get_alias_minimum_packet_rate_rule', + self.alt_target)) def test_create_policy_minimum_packet_rate_rule(self): self.assertTrue( @@ -1438,26 +1502,31 @@ class ProjectMemberQosMinimumPacketRateRuleTests( self.context = self.project_member_ctx def test_get_policy_minimum_packet_rate_rule(self): - self.assertTrue( - policy.enforce(self.context, - 'get_policy_minimum_packet_rate_rule', - self.target)) - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'get_policy_minimum_packet_rate_rule', - self.alt_target) - - # And the same for aliases - self.assertTrue( - policy.enforce(self.context, - 'get_alias_minimum_packet_rate_rule', - self.target)) - self.assertRaises( - base_policy.PolicyNotAuthorized, - policy.enforce, - self.context, 'get_alias_minimum_packet_rate_rule', - self.alt_target) + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.qos_policy): + self.assertTrue( + policy.enforce(self.context, + 'get_policy_minimum_packet_rate_rule', + self.target)) + # And the same for aliases + self.assertTrue( + policy.enforce(self.context, + 'get_alias_minimum_packet_rate_rule', + self.target)) + + with mock.patch.object(self.plugin_mock, "get_policy", + return_value=self.alt_qos_policy): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'get_policy_minimum_packet_rate_rule', + self.alt_target) + # And the same for aliases + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'get_alias_minimum_packet_rate_rule', + self.alt_target) def test_create_policy_minimum_packet_rate_rule(self): self.assertRaises( diff --git a/neutron/tests/unit/db/metering/test_metering_db.py b/neutron/tests/unit/db/metering/test_metering_db.py index 35d7f733c1..1c2af72a4e 100644 --- a/neutron/tests/unit/db/metering/test_metering_db.py +++ b/neutron/tests/unit/db/metering/test_metering_db.py @@ -16,7 +16,6 @@ import contextlib from neutron_lib.api.definitions import metering as metering_apidef from neutron_lib import constants as n_consts -from neutron_lib import context from neutron_lib.db import constants as db_const from neutron_lib.plugins import constants from oslo_utils import uuidutils @@ -42,18 +41,12 @@ _fake_uuid = uuidutils.generate_uuid class MeteringPluginDbTestCaseMixin(object): def _create_metering_label(self, fmt, name, description, **kwargs): data = {'metering_label': {'name': name, - 'tenant_id': kwargs.get('tenant_id', - 'test-tenant'), 'shared': kwargs.get('shared', False), 'description': description}} - req = self.new_create_request('metering-labels', data, - fmt) - - if kwargs.get('set_context') and 'tenant_id' in kwargs: - # create a specific auth context for this request - req.environ['neutron.context'] = ( - context.Context('', kwargs['tenant_id'], - is_admin=kwargs.get('is_admin', True))) + req = self.new_create_request( + 'metering-labels', data, fmt, + tenant_id=kwargs.get('tenant_id', self._tenant_id), + as_admin=kwargs.get('is_admin', True)) return req.get_response(self.ext_api) @@ -71,7 +64,6 @@ class MeteringPluginDbTestCaseMixin(object): data = { 'metering_label_rule': { 'metering_label_id': metering_label_id, - 'tenant_id': kwargs.get('tenant_id', 'test-tenant'), 'direction': direction, 'excluded': excluded, } @@ -87,13 +79,10 @@ class MeteringPluginDbTestCaseMixin(object): data['metering_label_rule']['destination_ip_prefix'] =\ destination_ip_prefix - req = self.new_create_request('metering-label-rules', - data, fmt) - - if kwargs.get('set_context') and 'tenant_id' in kwargs: - # create a specific auth context for this request - req.environ['neutron.context'] = ( - context.Context('', kwargs['tenant_id'])) + req = self.new_create_request( + 'metering-label-rules', data, fmt, + tenant_id=kwargs.get('tenant_id', self._tenant_id), + as_admin=kwargs.get('is_admin', True)) return req.get_response(self.ext_api) @@ -203,7 +192,8 @@ class TestMetering(MeteringPluginDbTestCase): with self.metering_label(name, description) as metering_label: metering_label_id = metering_label['metering_label']['id'] - self._delete('metering-labels', metering_label_id, 204) + self._delete('metering-labels', metering_label_id, 204, + as_admin=True) def test_list_metering_label(self): name = 'my label' @@ -258,7 +248,7 @@ class TestMetering(MeteringPluginDbTestCase): remote_ip_prefix=remote_ip_prefix) as label_rule: rule_id = label_rule['metering_label_rule']['id'] self._update('metering-label-rules', rule_id, data, - webob.exc.HTTPNotImplemented.code) + webob.exc.HTTPNotImplemented.code, as_admin=True) def test_delete_metering_label_rule(self): name = 'my label' @@ -275,7 +265,8 @@ class TestMetering(MeteringPluginDbTestCase): metering_label_id, direction, excluded, remote_ip_prefix=remote_ip_prefix) as label_rule: rule_id = label_rule['metering_label_rule']['id'] - self._delete('metering-label-rules', rule_id, 204) + self._delete('metering-label-rules', rule_id, 204, + as_admin=True) def test_list_metering_label_rule(self): name = 'my label' @@ -297,7 +288,7 @@ class TestMetering(MeteringPluginDbTestCase): metering_label_rule = (v1, v2) self._test_list_resources('metering-label-rule', - metering_label_rule) + metering_label_rule, as_admin=True) def test_create_metering_label_rules(self): name = 'my label' @@ -319,7 +310,7 @@ class TestMetering(MeteringPluginDbTestCase): metering_label_rule = (v1, v2) self._test_list_resources('metering-label-rule', - metering_label_rule) + metering_label_rule, as_admin=True) def test_create_overlap_metering_label_rules(self): name = 'my label' @@ -365,4 +356,5 @@ class TestMetering(MeteringPluginDbTestCase): metering_label_rule = (v1, v2) self._test_list_resources('metering-label-rule', - metering_label_rule) + metering_label_rule, + as_admin=True) diff --git a/neutron/tests/unit/db/test_agentschedulers_db.py b/neutron/tests/unit/db/test_agentschedulers_db.py index d503aee1ec..df4edfaa9b 100644 --- a/neutron/tests/unit/db/test_agentschedulers_db.py +++ b/neutron/tests/unit/db/test_agentschedulers_db.py @@ -45,6 +45,7 @@ from neutron.db.models import agent as agent_model from neutron.extensions import l3agentscheduler from neutron.objects import agent as ag_obj from neutron.objects import l3agent as rb_obj +from neutron import policy from neutron.tests.common import helpers from neutron.tests.unit.api import test_extensions from neutron.tests.unit.db import test_db_base_plugin_v2 as test_plugin @@ -78,18 +79,21 @@ class AgentSchedulerTestMixIn(object): def _path_req(self, path, method='GET', data=None, query_string=None, - admin_context=True): + admin_context=True, + req_tenant_id=None): content_type = 'application/%s' % self.fmt body = None if data is not None: # empty dict is valid body = wsgi.Serializer().serialize(data, content_type) + roles = ['member', 'reader'] + req_tenant_id = req_tenant_id or self._tenant_id if admin_context: - return testlib_api.create_request( - path, body, content_type, method, query_string=query_string) - else: - return testlib_api.create_request( - path, body, content_type, method, query_string=query_string, - context=context.Context('', 'tenant_id')) + roles.append('admin') + req = testlib_api.create_request( + path, body, content_type, method, query_string=query_string) + req.environ['neutron.context'] = context.Context( + '', req_tenant_id, roles=roles, is_admin=admin_context) + return req def _path_create_request(self, path, data, admin_context=True): return self._path_req(path, method='POST', data=data, @@ -218,7 +222,7 @@ class AgentSchedulerTestMixIn(object): new_agent = {} new_agent['agent'] = {} new_agent['agent']['admin_state_up'] = admin_state_up - self._update('agents', agent_id, new_agent) + self._update('agents', agent_id, new_agent, as_admin=True) def _get_agent_id(self, agent_type, host): agents = self._list_agents() @@ -269,6 +273,7 @@ class OvsAgentSchedulerTestCaseBase(test_l3.L3NatTestCaseMixin, self.dhcp_notify_p = mock.patch( 'neutron.extensions.dhcpagentscheduler.notify') self.patched_dhcp_notify = self.dhcp_notify_p.start() + policy.init() class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase): @@ -911,10 +916,12 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase): self.assertNotEqual(agent['host'], new_agent_host) def test_router_auto_schedule_with_invalid_router(self): - with self.router() as router: + project_id = uuidutils.generate_uuid() + with self.router(project_id=project_id) as router: l3_rpc_cb = l3_rpc.L3RpcCallback() self._register_agent_states() - self._delete('routers', router['router']['id']) + self._delete('routers', router['router']['id'], + tenant_id=project_id) # deleted router ret_a = l3_rpc_cb.sync_routers(self.adminContext, host=L3_HOSTA, @@ -1106,19 +1113,22 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase): self.assertEqual(0, len(router_ids)) def test_router_without_l3_agents(self): + project_id = uuidutils.generate_uuid() with self.subnet() as s: self._set_net_external(s['subnet']['network_id']) - data = {'router': {'tenant_id': uuidutils.generate_uuid()}} + data = {'router': {'tenant_id': project_id}} data['router']['name'] = 'router1' data['router']['external_gateway_info'] = { 'network_id': s['subnet']['network_id']} - router_req = self.new_create_request('routers', data, self.fmt) + router_req = self.new_create_request( + 'routers', data, self.fmt, tenant_id=project_id) res = router_req.get_response(self.ext_api) router = self.deserialize(self.fmt, res) l3agents = ( self.l3plugin.get_l3_agents_hosting_routers( self.adminContext, [router['router']['id']])) - self._delete('routers', router['router']['id']) + self._delete( + 'routers', router['router']['id'], tenant_id=project_id) self.assertEqual(0, len(l3agents)) def test_dvr_router_scheduling_to_only_dvr_snat_agent(self): @@ -1217,26 +1227,30 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase): self.assertEqual(agent['id'], new_agent['id']) def test_router_sync_data(self): - with self.subnet() as s1,\ - self.subnet(cidr='10.0.2.0/24') as s2,\ - self.subnet(cidr='10.0.3.0/24') as s3: + project_id = uuidutils.generate_uuid() + with self.subnet(project_id=project_id) as s1,\ + self.subnet(project_id=project_id, cidr='10.0.2.0/24') as s2,\ + self.subnet(project_id=project_id, cidr='10.0.3.0/24') as s3: self._register_agent_states() self._set_net_external(s1['subnet']['network_id']) - data = {'router': {'tenant_id': uuidutils.generate_uuid()}} + data = {'router': {'tenant_id': project_id}} data['router']['name'] = 'router1' data['router']['external_gateway_info'] = { 'network_id': s1['subnet']['network_id']} - router_req = self.new_create_request('routers', data, self.fmt) + router_req = self.new_create_request( + 'routers', data, self.fmt, tenant_id=project_id) res = router_req.get_response(self.ext_api) router = self.deserialize(self.fmt, res) self._router_interface_action('add', router['router']['id'], s2['subnet']['id'], - None) + None, + tenant_id=project_id) self._router_interface_action('add', router['router']['id'], s3['subnet']['id'], - None) + None, + tenant_id=project_id) l3agents = self._list_l3_agents_hosting_router( router['router']['id']) self.assertEqual(1, len(l3agents['agents'])) @@ -1267,7 +1281,8 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase): self._router_interface_action('remove', router['router']['id'], s2['subnet']['id'], - None) + None, + tenant_id=project_id) l3agents = self._list_l3_agents_hosting_router( router['router']['id']) self.assertEqual(1, @@ -1275,8 +1290,10 @@ class OvsAgentSchedulerTestCase(OvsAgentSchedulerTestCaseBase): self._router_interface_action('remove', router['router']['id'], s3['subnet']['id'], - None) - self._delete('routers', router['router']['id']) + None, + tenant_id=project_id) + self._delete('routers', router['router']['id'], + tenant_id=project_id) def _test_router_add_to_l3_agent(self, admin_state_up=True): with self.router() as router1: diff --git a/neutron/tests/unit/db/test_db_base_plugin_v2.py b/neutron/tests/unit/db/test_db_base_plugin_v2.py index a25ccc4f0d..9cb23e7192 100644 --- a/neutron/tests/unit/db/test_db_base_plugin_v2.py +++ b/neutron/tests/unit/db/test_db_base_plugin_v2.py @@ -49,6 +49,7 @@ import neutron from neutron.api import api_common from neutron.api import extensions from neutron.api.v2 import router +from neutron.common import _constants as common_constants from neutron.common import ipv6_utils from neutron.common.ovn import utils as ovn_utils from neutron.common import test_lib @@ -60,6 +61,8 @@ from neutron.db import ipam_backend_mixin from neutron.db.models import l3 as l3_models from neutron.db.models import securitygroup as sg_models from neutron.db import models_v2 +from neutron.db import rbac_db_models +from neutron.exceptions import mtu as mtu_exc from neutron.ipam.drivers.neutrondb_ipam import driver as ipam_driver from neutron.ipam import exceptions as ipam_exc from neutron.objects import network as network_obj @@ -246,60 +249,117 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): query_string=params, context=context, headers=headers) + def _admin_req(self, method, resource, data=None, fmt=None, id=None, + params=None, action=None, subresource=None, sub_id=None, + ctx=None, headers=None, tenant_id=None): + tenant_id = tenant_id or self._tenant_id + req = self._req(method, resource, data, fmt, id, params, action, + subresource, sub_id, ctx, headers) + req.environ['neutron.context'] = context.Context( + '', tenant_id, is_admin=True, + roles=['admin', 'member', 'reader']) + return req + + def _member_req(self, method, resource, data=None, fmt=None, id=None, + params=None, action=None, subresource=None, sub_id=None, + ctx=None, headers=None, tenant_id=None): + tenant_id = tenant_id or self._tenant_id + req = self._req(method, resource, data, fmt, id, params, action, + subresource, sub_id, ctx, headers) + req.environ['neutron.context'] = context.Context( + '', tenant_id, roles=['member', 'reader']) + return req + + def _reader_req(self, method, resource, data=None, fmt=None, id=None, + params=None, action=None, subresource=None, sub_id=None, + ctx=None, headers=None, tenant_id=None): + tenant_id = tenant_id or self._tenant_id + req = self._req(method, resource, data, fmt, id, params, action, + subresource, sub_id, ctx, headers) + req.environ['neutron.context'] = context.Context( + '', tenant_id, roles=['reader']) + return req + def new_create_request(self, resource, data, fmt=None, id=None, - subresource=None, context=None): - return self._req('POST', resource, data, fmt, id=id, - subresource=subresource, context=context) + subresource=None, context=None, tenant_id=None, + as_admin=False): + tenant_id = tenant_id or self._tenant_id + if as_admin: + return self._admin_req( + 'POST', resource, data, fmt, id=id, + subresource=subresource, ctx=context, tenant_id=tenant_id) + return self._member_req('POST', resource, data, fmt, id=id, + subresource=subresource, ctx=context, + tenant_id=tenant_id) def new_list_request(self, resource, fmt=None, params=None, - subresource=None, parent_id=None): - return self._req( + subresource=None, parent_id=None, tenant_id=None, + as_admin=False): + tenant_id = tenant_id or self._tenant_id + if as_admin: + return self._admin_req( + 'GET', resource, None, fmt, params=params, id=parent_id, + subresource=subresource, tenant_id=tenant_id + ) + return self._reader_req( 'GET', resource, None, fmt, params=params, id=parent_id, - subresource=subresource + subresource=subresource, tenant_id=tenant_id ) def new_show_request(self, resource, id, fmt=None, - subresource=None, fields=None, sub_id=None): + subresource=None, fields=None, sub_id=None, + tenant_id=None, as_admin=False): + tenant_id = tenant_id or self._tenant_id if fields: params = "&".join(["fields=%s" % x for x in fields]) else: params = None - return self._req('GET', resource, None, fmt, id=id, - params=params, subresource=subresource, sub_id=sub_id) + if as_admin: + return self._admin_req('GET', resource, None, fmt, id=id, + params=params, subresource=subresource, + sub_id=sub_id, tenant_id=tenant_id) + return self._reader_req('GET', resource, None, fmt, id=id, + params=params, subresource=subresource, + sub_id=sub_id, tenant_id=tenant_id) def new_delete_request(self, resource, id, fmt=None, subresource=None, - sub_id=None, data=None, headers=None): - return self._req( - 'DELETE', - resource, - data, - fmt, - id=id, - subresource=subresource, - sub_id=sub_id, - headers=headers - ) + sub_id=None, data=None, headers=None, + tenant_id=None, as_admin=False): + tenant_id = tenant_id or self._tenant_id + if as_admin: + return self._admin_req('DELETE', resource, data, fmt, id=id, + subresource=subresource, sub_id=sub_id, + headers=headers, tenant_id=tenant_id) + return self._member_req('DELETE', resource, data, fmt, id=id, + subresource=subresource, sub_id=sub_id, + headers=headers, tenant_id=tenant_id) def new_update_request(self, resource, data, id, fmt=None, subresource=None, context=None, sub_id=None, - headers=None): - return self._req( + headers=None, as_admin=False, tenant_id=None): + tenant_id = tenant_id or self._tenant_id + if as_admin: + return self._admin_req( + 'PUT', resource, data, fmt, id=id, subresource=subresource, + sub_id=sub_id, ctx=context, headers=headers, + tenant_id=tenant_id + ) + return self._member_req( 'PUT', resource, data, fmt, id=id, subresource=subresource, - sub_id=sub_id, context=context, headers=headers + sub_id=sub_id, ctx=context, headers=headers, tenant_id=tenant_id ) def new_action_request(self, resource, data, id, action, fmt=None, - subresource=None, sub_id=None): - return self._req( - 'PUT', - resource, - data, - fmt, - id=id, - action=action, - subresource=subresource, - sub_id=sub_id - ) + subresource=None, sub_id=None, tenant_id=None, + as_admin=False): + tenant_id = tenant_id or self._tenant_id + if as_admin: + return self._admin_req('PUT', resource, data, fmt, id=id, + action=action, subresource=subresource, + sub_id=sub_id, tenant_id=tenant_id) + return self._member_req('PUT', resource, data, fmt, id=id, + action=action, subresource=subresource, + sub_id=sub_id, tenant_id=tenant_id) def deserialize(self, content_type, response): ctype = 'application/%s' % content_type @@ -328,23 +388,19 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): return random.choice(ip_list) return ip_list[0] - def _create_bulk_from_list(self, fmt, resource, objects, **kwargs): + def _create_bulk_from_list(self, fmt, resource, objects, tenant_id=None, + as_admin=False, **kwargs): """Creates a bulk request from a list of objects.""" collection = "%ss" % resource req_data = {collection: objects} - req = self.new_create_request(collection, req_data, fmt) - if ('set_context' in kwargs and - kwargs['set_context'] is True and - 'tenant_id' in kwargs): - # create a specific auth context for this request - req.environ['neutron.context'] = context.Context( - '', kwargs['tenant_id']) - elif 'context' in kwargs: - req.environ['neutron.context'] = kwargs['context'] + req = self.new_create_request(collection, req_data, fmt, + tenant_id=tenant_id, as_admin=as_admin) return req.get_response(self.api) - def _create_bulk(self, fmt, number, resource, data, name='test', **kwargs): + def _create_bulk(self, fmt, number, resource, data, name='test', + tenant_id=None, as_admin=False, **kwargs): """Creates a bulk request for any kind of resource.""" + tenant_id = tenant_id or self._tenant_id objects = [] collection = "%ss" % resource for i in range(number): @@ -354,35 +410,27 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): obj[resource].update(kwargs['override'][i]) objects.append(obj) req_data = {collection: objects} - req = self.new_create_request(collection, req_data, fmt) - if ('set_context' in kwargs and - kwargs['set_context'] is True and - 'tenant_id' in kwargs): - # create a specific auth context for this request - req.environ['neutron.context'] = context.Context( - '', kwargs['tenant_id']) - elif 'context' in kwargs: - req.environ['neutron.context'] = kwargs['context'] + req = self.new_create_request(collection, req_data, fmt, + tenant_id=tenant_id, + as_admin=as_admin) return req.get_response(self.api) def _create_network(self, fmt, name, admin_state_up, - arg_list=None, set_context=False, tenant_id=None, + arg_list=None, tenant_id=None, as_admin=False, **kwargs): tenant_id = tenant_id or self._tenant_id data = {'network': {'name': name, 'admin_state_up': admin_state_up, 'tenant_id': tenant_id}} for arg in (('admin_state_up', 'tenant_id', 'shared', - 'vlan_transparent', + 'vlan_transparent', 'mtu', 'availability_zone_hints') + (arg_list or ())): # Arg must be present if arg in kwargs: data['network'][arg] = kwargs[arg] - network_req = self.new_create_request('networks', data, fmt) - if set_context and tenant_id: - # create a specific auth context for this request - network_req.environ['neutron.context'] = context.Context( - '', tenant_id) + network_req = self.new_create_request('networks', data, fmt, + tenant_id=tenant_id, + as_admin=as_admin) return network_req.get_response(self.api) @@ -392,11 +440,12 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): 'tenant_id': self._tenant_id}} return self._create_bulk(fmt, number, 'network', base_data, **kwargs) - def _create_subnet(self, fmt, net_id, cidr, - expected_res_status=None, **kwargs): + def _create_subnet(self, fmt, net_id, cidr, expected_res_status=None, + tenant_id=None, as_admin=False, **kwargs): + tenant_id = tenant_id or self._tenant_id data = {'subnet': {'network_id': net_id, 'ip_version': constants.IP_VERSION_4, - 'tenant_id': self._tenant_id}} + 'tenant_id': tenant_id}} if cidr: data['subnet']['cidr'] = cidr for arg in ('ip_version', 'tenant_id', 'subnetpool_id', 'prefixlen', @@ -412,11 +461,9 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): kwargs['gateway_ip'] is not constants.ATTR_NOT_SPECIFIED): data['subnet']['gateway_ip'] = kwargs['gateway_ip'] - subnet_req = self.new_create_request('subnets', data, fmt) - if (kwargs.get('set_context') and 'tenant_id' in kwargs): - # create a specific auth context for this request - subnet_req.environ['neutron.context'] = context.Context( - '', kwargs['tenant_id']) + subnet_req = self.new_create_request('subnets', data, fmt, + tenant_id=tenant_id, + as_admin=as_admin) subnet_res = subnet_req.get_response(self.api) if expected_res_status: @@ -443,24 +490,25 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): return self._create_bulk(fmt, number, 'subnet', base_data, **kwargs) def _create_subnetpool(self, fmt, prefixes, - expected_res_status=None, admin=False, **kwargs): + expected_res_status=None, admin=False, + tenant_id=None, **kwargs): + tenant_id = tenant_id or self._tenant_id subnetpool = {'subnetpool': {'prefixes': prefixes}} for k, v in kwargs.items(): subnetpool['subnetpool'][k] = str(v) api = self._api_for_resource('subnetpools') subnetpools_req = self.new_create_request('subnetpools', - subnetpool, fmt) - if not admin: - neutron_context = context.Context('', kwargs['tenant_id']) - subnetpools_req.environ['neutron.context'] = neutron_context + subnetpool, fmt, + tenant_id=tenant_id, + as_admin=admin) subnetpool_res = subnetpools_req.get_response(api) if expected_res_status: self.assertEqual(expected_res_status, subnetpool_res.status_int) return subnetpool_res def _create_port(self, fmt, net_id, expected_res_status=None, - arg_list=None, set_context=False, is_admin=False, + arg_list=None, is_admin=False, tenant_id=None, **kwargs): tenant_id = tenant_id or self._tenant_id data = {'port': {'network_id': net_id, @@ -470,7 +518,7 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): 'mac_address', 'name', 'fixed_ips', 'tenant_id', 'device_owner', 'security_groups', 'propagate_uplink_status', 'numa_affinity_policy', - 'device_profile') + (arg_list or ())): + 'device_profile', 'hints') + (arg_list or ())): # Arg must be present if arg in kwargs: data['port'][arg] = kwargs[arg] @@ -481,11 +529,9 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): 'device_id' not in kwargs): device_id = utils.get_dhcp_agent_device_id(net_id, kwargs['host']) data['port']['device_id'] = device_id - port_req = self.new_create_request('ports', data, fmt) - if set_context and tenant_id: - # create a specific auth context for this request - port_req.environ['neutron.context'] = context.Context( - '', tenant_id, is_admin=is_admin) + port_req = self.new_create_request('ports', data, fmt, + tenant_id=tenant_id, + as_admin=is_admin) port_res = port_req.get_response(self.api) if expected_res_status: @@ -499,28 +545,26 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): query_params.append("network_id=%s" % net_id) if kwargs.get('device_owner'): query_params.append("device_owner=%s" % kwargs.get('device_owner')) - port_req = self.new_list_request('ports', fmt, '&'.join(query_params)) - if ('set_context' in kwargs and - kwargs['set_context'] is True and - 'tenant_id' in kwargs): - # create a specific auth context for this request - port_req.environ['neutron.context'] = context.Context( - '', kwargs['tenant_id']) - + port_req = self.new_list_request('ports', fmt, '&'.join(query_params), + tenant_id=kwargs.get('tenant_id')) port_res = port_req.get_response(self.api) if expected_res_status: self.assertEqual(expected_res_status, port_res.status_int) return port_res def _create_port_bulk(self, fmt, number, net_id, name, - admin_state_up, **kwargs): + admin_state_up, tenant_id=None, as_admin=False, + **kwargs): base_data = {'port': {'network_id': net_id, - 'admin_state_up': admin_state_up, - 'tenant_id': self._tenant_id}} - return self._create_bulk(fmt, number, 'port', base_data, **kwargs) - - def _make_network(self, fmt, name, admin_state_up, **kwargs): - res = self._create_network(fmt, name, admin_state_up, **kwargs) + 'admin_state_up': admin_state_up}} + return self._create_bulk(fmt, number, 'port', base_data, + tenant_id=tenant_id, as_admin=as_admin, + **kwargs) + + def _make_network(self, fmt, name, admin_state_up, as_admin=False, + **kwargs): + res = self._create_network(fmt, name, admin_state_up, + as_admin=as_admin, **kwargs) # TODO(salvatore-orlando): do exception handling in this test module # in a uniform way (we do it differently for ports, subnets, and nets # Things can go wrong - raise HTTP exc with res code only @@ -533,7 +577,7 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): allocation_pools=None, ip_version=constants.IP_VERSION_4, enable_dhcp=True, dns_nameservers=None, host_routes=None, shared=None, ipv6_ra_mode=None, ipv6_address_mode=None, - tenant_id=None, set_context=False, segment_id=None): + tenant_id=None, segment_id=None, as_admin=False): res = self._create_subnet(fmt, net_id=network['network']['id'], cidr=cidr, @@ -550,7 +594,7 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): shared=shared, ipv6_ra_mode=ipv6_ra_mode, ipv6_address_mode=ipv6_address_mode, - set_context=set_context) + as_admin=as_admin) # Things can go wrong - raise HTTP exc with res code only # so it can be caught by unit tests if res.status_int >= webob.exc.HTTPClientError.code: @@ -572,11 +616,13 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): ipv6_ra_mode=ra_addr_mode, ipv6_address_mode=ra_addr_mode)) - def _make_subnetpool(self, fmt, prefixes, admin=False, **kwargs): + def _make_subnetpool(self, fmt, prefixes, admin=False, tenant_id=None, + **kwargs): res = self._create_subnetpool(fmt, prefixes, None, admin, + tenant_id=tenant_id, **kwargs) # Things can go wrong - raise HTTP exc with res code only # so it can be caught by unit tests @@ -584,8 +630,10 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): raise webob.exc.HTTPClientError(code=res.status_int) return self.deserialize(fmt, res) - def _make_port(self, fmt, net_id, expected_res_status=None, **kwargs): - res = self._create_port(fmt, net_id, expected_res_status, **kwargs) + def _make_port(self, fmt, net_id, expected_res_status=None, + as_admin=False, **kwargs): + res = self._create_port(fmt, net_id, expected_res_status, + is_admin=as_admin, **kwargs) # Things can go wrong - raise HTTP exc with res code only # so it can be caught by unit tests if res.status_int >= webob.exc.HTTPClientError.code: @@ -596,7 +644,7 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): max_burst_kbps=None, dscp_mark=None, min_kbps=None, direction=constants.EGRESS_DIRECTION, expected_res_status=None, project_id=None, - set_context=False, is_admin=False): + is_admin=False): # Accepted rule types: "bandwidth_limit", "dscp_marking" and # "minimum_bandwidth" self.assertIn(rule_type, [qos_const.RULE_TYPE_BANDWIDTH_LIMIT, @@ -615,11 +663,9 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): data[type_req][qos_const.MIN_KBPS] = min_kbps data[type_req][qos_const.DIRECTION] = direction route = 'qos/policies/%s/%s' % (qos_policy_id, type_req + 's') - qos_rule_req = self.new_create_request(route, data, fmt) - if set_context and project_id: - # create a specific auth context for this request - qos_rule_req.environ['neutron.context'] = context.Context( - '', project_id, is_admin=is_admin) + qos_rule_req = self.new_create_request(route, data, fmt, + tenant_id=project_id, + as_admin=is_admin) qos_rule_res = qos_rule_req.get_response(self.api) if expected_res_status: @@ -628,16 +674,14 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): def _create_qos_policy(self, fmt, qos_policy_name=None, expected_res_status=None, project_id=None, - set_context=False, is_admin=False): + is_admin=False): project_id = project_id or self._tenant_id name = qos_policy_name or uuidutils.generate_uuid() data = {'policy': {'name': name, 'project_id': project_id}} - qos_req = self.new_create_request('policies', data, fmt) - if set_context and project_id: - # create a specific auth context for this request - qos_req.environ['neutron.context'] = context.Context( - '', project_id, is_admin=is_admin) + qos_req = self.new_create_request('policies', data, fmt, + tenant_id=project_id, + as_admin=is_admin) qos_policy_res = qos_req.get_response(self.api) if expected_res_status: @@ -653,54 +697,49 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): def _delete(self, collection, id, expected_code=webob.exc.HTTPNoContent.code, - neutron_context=None, headers=None, subresource=None, - sub_id=None): + headers=None, subresource=None, sub_id=None, + tenant_id=None, as_admin=False): req = self.new_delete_request(collection, id, headers=headers, - subresource=subresource, sub_id=sub_id) - if neutron_context: - # create a specific auth context for this request - req.environ['neutron.context'] = neutron_context + subresource=subresource, sub_id=sub_id, + tenant_id=tenant_id, as_admin=as_admin) + res = req.get_response(self._api_for_resource(collection)) self.assertEqual(expected_code, res.status_int) - def _show_response(self, resource, id, neutron_context=None): - req = self.new_show_request(resource, id) - if neutron_context: - # create a specific auth context for this request - req.environ['neutron.context'] = neutron_context - elif hasattr(self, 'tenant_id'): - req.environ['neutron.context'] = context.Context('', - self.tenant_id) + def _show_response(self, resource, id, tenant_id=None, as_admin=False): + req = self.new_show_request(resource, id, + tenant_id=tenant_id, + as_admin=as_admin) return req.get_response(self._api_for_resource(resource)) def _show(self, resource, id, expected_code=webob.exc.HTTPOk.code, - neutron_context=None): - res = self._show_response(resource, id, - neutron_context=neutron_context) + tenant_id=None, as_admin=False): + res = self._show_response(resource, id, tenant_id=tenant_id, + as_admin=as_admin) self.assertEqual(expected_code, res.status_int) return self.deserialize(self.fmt, res) def _update(self, resource, id, new_data, - expected_code=webob.exc.HTTPOk.code, - neutron_context=None, headers=None): - req = self.new_update_request(resource, new_data, id, headers=headers) - if neutron_context: - # create a specific auth context for this request - req.environ['neutron.context'] = neutron_context + expected_code=webob.exc.HTTPOk.code, headers=None, + request_tenant_id=None, as_admin=False): + req = self.new_update_request( + resource, new_data, id, headers=headers, + tenant_id=request_tenant_id, as_admin=as_admin) res = req.get_response(self._api_for_resource(resource)) self.assertEqual(expected_code, res.status_int) return self.deserialize(self.fmt, res) - def _list(self, resource, fmt=None, neutron_context=None, + def _list(self, resource, fmt=None, query_params=None, expected_code=webob.exc.HTTPOk.code, - parent_id=None, subresource=None): + parent_id=None, subresource=None, + tenant_id=None, as_admin=False): fmt = fmt or self.fmt req = self.new_list_request(resource, fmt, query_params, subresource=subresource, - parent_id=parent_id) - if neutron_context: - req.environ['neutron.context'] = neutron_context + parent_id=parent_id, + tenant_id=tenant_id, + as_admin=as_admin) res = req.get_response(self._api_for_resource(resource)) self.assertEqual(expected_code, res.status_int) return self.deserialize(fmt, res) @@ -730,13 +769,14 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): self.assertEqual(items[0]['name'], 'test_0') self.assertEqual(items[1]['name'], 'test_1') - def _test_list_resources(self, resource, items, neutron_context=None, - query_params=None, - expected_code=webob.exc.HTTPOk.code): + def _test_list_resources(self, resource, items, query_params=None, + expected_code=webob.exc.HTTPOk.code, + tenant_id=None, as_admin=False): res = self._list('%ss' % resource, - neutron_context=neutron_context, query_params=query_params, - expected_code=expected_code) + expected_code=expected_code, + tenant_id=tenant_id, + as_admin=as_admin) if expected_code == webob.exc.HTTPOk.code: resource = resource.replace('-', '_') self.assertCountEqual([i['id'] for i in res['%ss' % resource]], @@ -771,7 +811,7 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): tenant_id=None, project_id=None, service_types=None, - set_context=False): + as_admin=False): if project_id: tenant_id = project_id cidr = netaddr.IPNetwork(cidr) if cidr else None @@ -780,7 +820,6 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): gateway_ip = netaddr.IPAddress(gateway_ip) with optional_ctx(network, self.network, - set_context=set_context, tenant_id=tenant_id) as network_to_use: subnet = self._make_subnet(fmt or self.fmt, network_to_use, @@ -797,7 +836,7 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): ipv6_ra_mode=ipv6_ra_mode, ipv6_address_mode=ipv6_address_mode, tenant_id=tenant_id, - set_context=set_context) + as_admin=as_admin) yield subnet @contextlib.contextmanager @@ -811,22 +850,22 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): yield subnetpool @contextlib.contextmanager - def port(self, subnet=None, fmt=None, set_context=False, project_id=None, + def port(self, subnet=None, fmt=None, project_id=None, is_admin=False, **kwargs): tenant_id = project_id if project_id else kwargs.pop( 'tenant_id', None) with optional_ctx( subnet, self.subnet, - set_context=set_context, tenant_id=tenant_id) as subnet_to_use: + tenant_id=tenant_id) as subnet_to_use: net_id = subnet_to_use['subnet']['network_id'] port = self._make_port( - fmt or self.fmt, net_id, - set_context=set_context, tenant_id=tenant_id, - **kwargs) + fmt or self.fmt, net_id, tenant_id=tenant_id, + as_admin=is_admin, **kwargs) yield port def _test_list_with_sort(self, resource, - items, sorts, resources=None, query_params=''): + items, sorts, resources=None, query_params='', + tenant_id=None, as_admin=False): query_str = query_params for key, direction in sorts: query_str = query_str + "&sort_key=%s&sort_dir=%s" % (key, @@ -834,7 +873,9 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): if not resources: resources = '%ss' % resource req = self.new_list_request(resources, - params=query_str) + params=query_str, + tenant_id=tenant_id, + as_admin=as_admin) api = self._api_for_resource(resources) res = self.deserialize(self.fmt, req.get_response(api)) resource = resource.replace('-', '_') @@ -846,13 +887,17 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): limit, expected_page_num, resources=None, query_params='', - verify_key='id'): + verify_key='id', + tenant_id=None, + as_admin=False): if not resources: resources = '%ss' % resource query_str = query_params + '&' if query_params else '' query_str = query_str + ("limit=%s&sort_key=%s&" "sort_dir=%s") % (limit, sort[0], sort[1]) - req = self.new_list_request(resources, params=query_str) + req = self.new_list_request(resources, params=query_str, + tenant_id=tenant_id, as_admin=as_admin) + neutron_ctx = req.environ['neutron.context'] items_res = [] page_num = 0 api = self._api_for_resource(resources) @@ -871,6 +916,7 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): content_type = 'application/%s' % self.fmt req = testlib_api.create_request(link['href'], '', content_type) + req.environ['neutron.context'] = neutron_ctx self.assertEqual(len(res[resources]), limit) self.assertEqual(expected_page_num, page_num) @@ -880,7 +926,9 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): def _test_list_with_pagination_reverse(self, resource, items, sort, limit, expected_page_num, resources=None, - query_params=''): + query_params='', + tenant_id=None, + as_admin=False): if not resources: resources = '%ss' % resource resource = resource.replace('-', '_') @@ -891,7 +939,9 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): "sort_key=%s&sort_dir=%s&" "marker=%s") % (limit, sort[0], sort[1], marker) - req = self.new_list_request(resources, params=query_str) + req = self.new_list_request(resources, params=query_str, + tenant_id=tenant_id, as_admin=as_admin) + neutron_ctx = req.environ['neutron.context'] item_res = [items[-1][resource]] page_num = 0 resources = resources.replace('-', '_') @@ -909,6 +959,7 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): content_type = 'application/%s' % self.fmt req = testlib_api.create_request(link['href'], '', content_type) + req.environ['neutron.context'] = neutron_ctx self.assertEqual(len(res[resources]), limit) self.assertEqual(expected_page_num, page_num) @@ -1001,10 +1052,9 @@ class TestV2HTTPResponse(NeutronDbPluginV2TestCase): self._create_network(self.fmt, 'some_net', True, - tenant_id=tenant_id, - set_context=True) - req = self.new_list_request('networks', params="fields=name") - req.environ['neutron.context'] = context.Context('', tenant_id) + tenant_id=tenant_id) + req = self.new_list_request( + 'networks', params="fields=name", tenant_id=tenant_id) res = req.get_response(self.api) self._check_list_with_fields(res, 'name') @@ -1020,10 +1070,9 @@ class TestV2HTTPResponse(NeutronDbPluginV2TestCase): self._create_network(self.fmt, 'some_net', True, - tenant_id=tenant_id, - set_context=True) - req = self.new_list_request('networks', params="fields=tenant_id") - req.environ['neutron.context'] = context.Context('', tenant_id) + tenant_id=tenant_id) + req = self.new_list_request( + 'networks', params="fields=tenant_id", tenant_id=tenant_id) res = req.get_response(self.api) self._check_list_with_fields(res, 'tenant_id') @@ -1086,7 +1135,7 @@ class TestPortsV2(NeutronDbPluginV2TestCase): def test_create_port_json(self): keys = [('admin_state_up', True), ('status', self.port_create_status)] - with self.network(shared=True) as network: + with self.network(shared=True, as_admin=True) as network: with self.subnet(network=network) as subnet: with self.port(name='myname', subnet=subnet) as port: for k, v in keys: @@ -1108,7 +1157,7 @@ class TestPortsV2(NeutronDbPluginV2TestCase): device_id='fake_device', device_owner='fake_owner', fixed_ips=[], - set_context=False) + is_admin=True) def test_create_port_bad_tenant(self): with self.network() as network: @@ -1118,17 +1167,15 @@ class TestPortsV2(NeutronDbPluginV2TestCase): tenant_id='bad_tenant_id', device_id='fake_device', device_owner='fake_owner', - fixed_ips=[], - set_context=True) + fixed_ips=[]) def test_create_port_public_network(self): keys = [('admin_state_up', True), ('status', self.port_create_status)] - with self.network(shared=True) as network: + with self.network(shared=True, as_admin=True) as network: port_res = self._create_port(self.fmt, network['network']['id'], webob.exc.HTTPCreated.code, - tenant_id='another_tenant', - set_context=True) + tenant_id='another_tenant') port = self.deserialize(self.fmt, port_res) for k, v in keys: self.assertEqual(port['port'][k], v) @@ -1147,11 +1194,10 @@ class TestPortsV2(NeutronDbPluginV2TestCase): webob.exc.HTTPClientError.code, tenant_id='tenant_id', fixed_ips=[], - set_context=False, **kwargs) def test_create_port_public_network_with_ip(self): - with self.network(shared=True) as network: + with self.network(shared=True, as_admin=True) as network: ip_net = netaddr.IPNetwork('10.0.0.0/24') with self.subnet(network=network, cidr=str(ip_net)): keys = [('admin_state_up', True), @@ -1159,8 +1205,7 @@ class TestPortsV2(NeutronDbPluginV2TestCase): port_res = self._create_port(self.fmt, network['network']['id'], webob.exc.HTTPCreated.code, - tenant_id='another_tenant', - set_context=True) + tenant_id='another_tenant') port = self.deserialize(self.fmt, port_res) for k, v in keys: self.assertEqual(port['port'][k], v) @@ -1170,7 +1215,7 @@ class TestPortsV2(NeutronDbPluginV2TestCase): self._delete('ports', port['port']['id']) def test_create_port_anticipating_allocation(self): - with self.network(shared=True) as network: + with self.network(shared=True, as_admin=True) as network: with self.subnet(network=network, cidr='10.0.0.0/24') as subnet: fixed_ips = [{'subnet_id': subnet['subnet']['id']}, {'subnet_id': subnet['subnet']['id'], @@ -1181,14 +1226,13 @@ class TestPortsV2(NeutronDbPluginV2TestCase): def test_create_port_public_network_with_invalid_ip_no_subnet_id(self, expected_error='InvalidIpForNetwork'): - with self.network(shared=True) as network: + with self.network(shared=True, as_admin=True) as network: with self.subnet(network=network, cidr='10.0.0.0/24'): ips = [{'ip_address': '1.1.1.1'}] res = self._create_port(self.fmt, network['network']['id'], webob.exc.HTTPBadRequest.code, - fixed_ips=ips, - set_context=True) + fixed_ips=ips) data = self.deserialize(self.fmt, res) msg = str(lib_exc.InvalidIpForNetwork(ip_address='1.1.1.1')) self.assertEqual(expected_error, data['NeutronError']['type']) @@ -1196,15 +1240,14 @@ class TestPortsV2(NeutronDbPluginV2TestCase): def test_create_port_public_network_with_invalid_ip_and_subnet_id(self, expected_error='InvalidIpForSubnet'): - with self.network(shared=True) as network: + with self.network(shared=True, as_admin=True) as network: with self.subnet(network=network, cidr='10.0.0.0/24') as subnet: ips = [{'subnet_id': subnet['subnet']['id'], 'ip_address': '1.1.1.1'}] res = self._create_port(self.fmt, network['network']['id'], webob.exc.HTTPBadRequest.code, - fixed_ips=ips, - set_context=True) + fixed_ips=ips) data = self.deserialize(self.fmt, res) msg = str(lib_exc.InvalidIpForSubnet(ip_address='1.1.1.1')) self.assertEqual(expected_error, data['NeutronError']['type']) @@ -1342,29 +1385,29 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s self._test_list_ports_filtered_by_fixed_ip(limit=500) def test_list_ports_public_network(self): - with self.network(shared=True) as network: + with self.network(shared=True, as_admin=True) as network: with self.subnet(network) as subnet: with self.port(subnet, tenant_id='tenant_1') as port1,\ self.port(subnet, tenant_id='tenant_2') as port2: # Admin request - must return both ports - self._test_list_resources('port', [port1, port2]) + self._test_list_resources( + 'port', [port1, port2], as_admin=True) # Tenant_1 request - must return single port - n_context = context.Context('', 'tenant_1') self._test_list_resources('port', [port1], - neutron_context=n_context) + tenant_id='tenant_1') # Tenant_2 request - must return single port - n_context = context.Context('', 'tenant_2') self._test_list_resources('port', [port2], - neutron_context=n_context) + tenant_id='tenant_2') def test_list_ports_for_network_owner(self): with self.network(tenant_id='tenant_1') as network: - with self.subnet(network) as subnet: - with self.port(subnet, tenant_id='tenant_1') as port1,\ - self.port(subnet, tenant_id='tenant_2') as port2: + with self.subnet(network, tenant_id='tenant_1') as subnet: + with self.port(subnet, project_id='tenant_1') as port1,\ + self.port(subnet, project_id='tenant_2', + is_admin=True) as port2: # network owner request, should return all ports port_res = self._list_ports( - 'json', set_context=True, tenant_id='tenant_1') + 'json', tenant_id='tenant_1') port_list = self.deserialize('json', port_res)['ports'] port_ids = [p['id'] for p in port_list] self.assertEqual(2, len(port_list)) @@ -1373,7 +1416,7 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s # another tenant request, only return ports belong to it port_res = self._list_ports( - 'json', set_context=True, tenant_id='tenant_2') + 'json', tenant_id='tenant_2') port_list = self.deserialize('json', port_res)['ports'] port_ids = [p['id'] for p in port_list] self.assertEqual(1, len(port_list)) @@ -1467,12 +1510,11 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s expected_code=webob.exc.HTTPNotFound.code) def test_delete_port_public_network(self): - with self.network(shared=True) as network: + with self.network(shared=True, as_admin=True) as network: port_res = self._create_port(self.fmt, network['network']['id'], webob.exc.HTTPCreated.code, - tenant_id='another_tenant', - set_context=True) + tenant_id='another_tenant') port = self.deserialize(self.fmt, port_res) self._delete('ports', port['port']['id']) @@ -1482,15 +1524,15 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s def test_delete_port_by_network_owner(self): with self.network(tenant_id='tenant_1') as network: with self.subnet(network) as subnet: - with self.port(subnet, tenant_id='tenant_2') as port: + with self.port(subnet, tenant_id='tenant_2', + is_admin=True) as port: self._delete( - 'ports', port['port']['id'], - neutron_context=context.Context('', 'tenant_1')) + 'ports', port['port']['id'], tenant_id='tenant_1') self._show('ports', port['port']['id'], expected_code=webob.exc.HTTPNotFound.code) def test_update_port_with_stale_subnet(self): - with self.network(shared=True) as network: + with self.network(shared=True, as_admin=True) as network: port = self._make_port(self.fmt, network['network']['id']) subnet = self._make_subnet(self.fmt, network, '10.0.0.1', '10.0.0.0/24') @@ -1528,7 +1570,8 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s data = {'port': {'mac_address': new_mac}} if updated_fixed_ips: data['port']['fixed_ips'] = updated_fixed_ips - req = self.new_update_request('ports', data, port['id']) + req = self.new_update_request( + 'ports', data, port['id'], as_admin=True) return req.get_response(self.api), new_mac def _verify_ips_after_mac_change(self, orig_port, new_port): @@ -1553,6 +1596,7 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s host_arg = host_arg or {} arg_list = arg_list or [] with self.port(device_owner=device_owner, subnet=subnet, + is_admin=True, arg_list=arg_list, **host_arg) as port: self.assertIn('mac_address', port['port']) res, new_mac = self.update_port_mac( @@ -1634,7 +1678,8 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s new_mac = port2['port']['mac_address'] data = {'port': {'mac_address': new_mac}} req = self.new_update_request('ports', data, - port['port']['id']) + port['port']['id'], + as_admin=True) res = req.get_response(self.api) self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) @@ -1647,16 +1692,14 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s def test_update_port_not_admin(self): res = self._create_network(self.fmt, 'net1', True, - tenant_id='not_admin', - set_context=True) + tenant_id='not_admin') net1 = self.deserialize(self.fmt, res) res = self._create_port(self.fmt, net1['network']['id'], - tenant_id='not_admin', set_context=True) + tenant_id='not_admin') port = self.deserialize(self.fmt, res) data = {'port': {'admin_state_up': False}} - neutron_context = context.Context('', 'not_admin') port = self._update('ports', port['port']['id'], data, - neutron_context=neutron_context) + request_tenant_id='not_admin') self.assertFalse(port['port']['admin_state_up']) def test_update_device_id_unchanged(self): @@ -2746,7 +2789,7 @@ class TestNetworksV2(NeutronDbPluginV2TestCase): name = 'public_net' keys = [('subnets', []), ('name', name), ('admin_state_up', True), ('status', self.net_create_status), ('shared', True)] - with self.network(name=name, shared=True) as net: + with self.network(name=name, shared=True, as_admin=True) as net: for k, v in keys: self.assertEqual(net['network'][k], v) @@ -2756,8 +2799,7 @@ class TestNetworksV2(NeutronDbPluginV2TestCase): webob.exc.HTTPClientError) as ctx_manager: with self.network(name=name, shared=True, - tenant_id="another_tenant", - set_context=True): + tenant_id="another_tenant"): pass self.assertEqual(webob.exc.HTTPForbidden.code, ctx_manager.exception.code) @@ -2773,12 +2815,12 @@ class TestNetworksV2(NeutronDbPluginV2TestCase): res['network']['name']) def test_update_shared_network_noadmin_returns_403(self): - with self.network(shared=True) as network: + with self.network(shared=True, as_admin=True) as network: data = {'network': {'name': 'a_brand_new_name'}} req = self.new_update_request('networks', data, - network['network']['id']) - req.environ['neutron.context'] = context.Context('', 'somebody') + network['network']['id'], + tenant_id='other-tenant') res = req.get_response(self.api) self.assertEqual(403, res.status_int) @@ -2787,7 +2829,8 @@ class TestNetworksV2(NeutronDbPluginV2TestCase): data = {'network': {'shared': True}} req = self.new_update_request('networks', data, - network['network']['id']) + network['network']['id'], + as_admin=True) res = self.deserialize(self.fmt, req.get_response(self.api)) self.assertTrue(res['network']['shared']) @@ -2808,7 +2851,8 @@ class TestNetworksV2(NeutronDbPluginV2TestCase): data = {'network': {'shared': True}} req = self.new_update_request('networks', data, - network['network']['id']) + network['network']['id'], + as_admin=True) res = self.deserialize(self.fmt, req.get_response(self.api)) self.assertTrue(res['network']['shared']) # must query db to see whether subnet's shared attribute @@ -2819,81 +2863,79 @@ class TestNetworksV2(NeutronDbPluginV2TestCase): self.assertTrue(subnet_db['shared']) def test_update_network_set_not_shared_single_tenant(self): - with self.network(shared=True) as network: + with self.network(shared=True, as_admin=True) as network: res1 = self._create_port(self.fmt, network['network']['id'], webob.exc.HTTPCreated.code, - tenant_id=network['network']['tenant_id'], - set_context=True) + tenant_id=network['network']['tenant_id']) data = {'network': {'shared': False}} req = self.new_update_request('networks', data, - network['network']['id']) + network['network']['id'], + as_admin=True) res = self.deserialize(self.fmt, req.get_response(self.api)) self.assertFalse(res['network']['shared']) port1 = self.deserialize(self.fmt, res1) self._delete('ports', port1['port']['id']) - def test_update_network_set_not_shared_other_tenant_returns_409(self): - with self.network(shared=True) as network: + def test_update_network_set_not_shared_other_tenant_returns_403(self): + with self.network(shared=True, as_admin=True) as network: res1 = self._create_port(self.fmt, network['network']['id'], webob.exc.HTTPCreated.code, - tenant_id='somebody_else', - set_context=True) + tenant_id='somebody_else') data = {'network': {'shared': False}} req = self.new_update_request('networks', data, network['network']['id']) - self.assertEqual(webob.exc.HTTPConflict.code, + self.assertEqual(webob.exc.HTTPForbidden.code, req.get_response(self.api).status_int) port1 = self.deserialize(self.fmt, res1) self._delete('ports', port1['port']['id']) def test_update_network_set_not_shared_other_tenant_access_via_rbac(self): - with self.network(shared=True) as network: + with self.network(shared=True, as_admin=True) as network: ctx = context.get_admin_context() with db_api.CONTEXT_WRITER.using(ctx): network_obj.NetworkRBAC( ctx, object_id=network['network']['id'], - action='access_as_shared', + action=rbac_db_models.ACCESS_SHARED, project_id=network['network']['tenant_id'], target_project='somebody_else').create() network_obj.NetworkRBAC( ctx, object_id=network['network']['id'], - action='access_as_shared', + action=rbac_db_models.ACCESS_SHARED, project_id=network['network']['tenant_id'], target_project='one_more_somebody_else').create() res1 = self._create_port(self.fmt, network['network']['id'], webob.exc.HTTPCreated.code, - tenant_id='somebody_else', - set_context=True) + tenant_id='somebody_else') data = {'network': {'shared': False}} req = self.new_update_request('networks', data, - network['network']['id']) + network['network']['id'], + as_admin=True) res = self.deserialize(self.fmt, req.get_response(self.api)) self.assertFalse(res['network']['shared']) port1 = self.deserialize(self.fmt, res1) self._delete('ports', port1['port']['id']) def test_update_network_set_not_shared_multi_tenants_returns_409(self): - with self.network(shared=True) as network: + with self.network(shared=True, as_admin=True) as network: res1 = self._create_port(self.fmt, network['network']['id'], webob.exc.HTTPCreated.code, - tenant_id='somebody_else', - set_context=True) + tenant_id='somebody_else') res2 = self._create_port(self.fmt, network['network']['id'], webob.exc.HTTPCreated.code, - tenant_id=network['network']['tenant_id'], - set_context=True) + tenant_id=network['network']['tenant_id']) data = {'network': {'shared': False}} req = self.new_update_request('networks', data, - network['network']['id']) + network['network']['id'], + as_admin=True) self.assertEqual(webob.exc.HTTPConflict.code, req.get_response(self.api).status_int) port1 = self.deserialize(self.fmt, res1) @@ -2902,22 +2944,21 @@ class TestNetworksV2(NeutronDbPluginV2TestCase): self._delete('ports', port2['port']['id']) def test_update_network_set_not_shared_multi_tenants2_returns_409(self): - with self.network(shared=True) as network: + with self.network(shared=True, as_admin=True) as network: res1 = self._create_port(self.fmt, network['network']['id'], webob.exc.HTTPCreated.code, - tenant_id='somebody_else', - set_context=True) + tenant_id='somebody_else') self._create_subnet(self.fmt, network['network']['id'], '10.0.0.0/24', webob.exc.HTTPCreated.code, - tenant_id=network['network']['tenant_id'], - set_context=True) + tenant_id=network['network']['tenant_id']) data = {'network': {'shared': False}} req = self.new_update_request('networks', data, - network['network']['id']) + network['network']['id'], + as_admin=True) self.assertEqual(webob.exc.HTTPConflict.code, req.get_response(self.api).status_int) @@ -2967,7 +3008,8 @@ class TestNetworksV2(NeutronDbPluginV2TestCase): {'network': {'name': 'n2', 'tenant_id': 't1'}}] - res = self._create_bulk_from_list(self.fmt, 'network', networks) + res = self._create_bulk_from_list(self.fmt, 'network', networks, + as_admin=True) self.assertEqual(webob.exc.HTTPCreated.code, res.status_int) def test_create_networks_bulk_tenants_and_quotas_fail(self): @@ -2987,7 +3029,8 @@ class TestNetworksV2(NeutronDbPluginV2TestCase): {'network': {'name': 'n2', 'tenant_id': 't1'}}] - res = self._create_bulk_from_list(self.fmt, 'network', networks) + res = self._create_bulk_from_list(self.fmt, 'network', networks, + as_admin=True) self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) def test_create_networks_bulk_emulated(self): @@ -3136,9 +3179,9 @@ class TestNetworksV2(NeutronDbPluginV2TestCase): 'neutron.api.v2.base.Controller._get_pagination_helper', new=_fake_get_pagination_helper) helper_patcher.start() - with self.network(name='net1', shared=True) as net1,\ + with self.network(name='net1', shared=True, as_admin=True) as net1,\ self.network(name='net2', shared=False) as net2,\ - self.network(name='net3', shared=True) as net3: + self.network(name='net3', shared=True, as_admin=True) as net3: self._test_list_with_pagination('network', (net1, net2, net3), ('name', 'asc'), 2, 2, @@ -3215,14 +3258,13 @@ class TestNetworksV2(NeutronDbPluginV2TestCase): tenant_id='tenant1') as net1,\ self.network(shared=True, name='net2', + as_admin=True, tenant_id='another_tenant') as net2,\ self.network(shared=False, name='net3', tenant_id='another_tenant'): - ctx = context.Context(user_id='non_admin', - tenant_id='tenant1', - is_admin=False) - self._test_list_resources('network', (net1, net2), ctx) + self._test_list_resources('network', (net1, net2), + tenant_id='tenant1') def test_show_network(self): with self.network(name='net1') as net: @@ -3760,8 +3802,7 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase): ip_version=constants.IP_VERSION_4, tenant_id='bad_tenant_id', gateway_ip='10.0.2.1', - device_owner='fake_owner', - set_context=True) + device_owner='fake_owner') def test_create_subnet_as_admin(self): with self.network() as network: @@ -3773,7 +3814,7 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase): tenant_id='bad_tenant_id', gateway_ip='10.0.2.1', device_owner='fake_owner', - set_context=False) + as_admin=True) def test_create_subnet_nonzero_cidr(self): # Pass None as gateway_ip to prevent ip auto allocation for gw @@ -4464,7 +4505,8 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase): 'tenant_id': 'tenant_id', 'device_id': 'fake_device', 'device_owner': constants.DEVICE_OWNER_ROUTER_GW} - res = self._create_port(self.fmt, net_id=net_id, **kwargs) + res = self._create_port(self.fmt, net_id=net_id, + is_admin=True, **kwargs) self.assertEqual(webob.exc.HTTPCreated.code, res.status_int) def test_create_subnet_ipv6_first_ip_owned_by_non_router(self): @@ -4480,7 +4522,8 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase): 'tenant_id': 'tenant_id', 'device_id': 'fake_device', 'device_owner': 'fake_owner'} - res = self._create_port(self.fmt, net_id=net_id, **kwargs) + res = self._create_port(self.fmt, net_id=net_id, + is_admin=True, **kwargs) self.assertEqual(webob.exc.HTTPClientError.code, res.status_int) @@ -4804,7 +4847,7 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase): ra_addr_mode=constants.DHCPV6_STATELESS) def test_update_subnet_shared_returns_400(self): - with self.network(shared=True) as network: + with self.network(shared=True, as_admin=True) as network: with self.subnet(network=network) as subnet: data = {'subnet': {'shared': True}} req = self.new_update_request('subnets', data, @@ -5294,7 +5337,8 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase): with self.subnet(network=network, gateway_ip='10.0.0.1', cidr='10.0.0.0/24', - tenant_id=project_id),\ + tenant_id=project_id, + as_admin=True),\ self.subnet(network=network, gateway_ip='10.0.1.1', cidr='10.0.1.0/24'),\ @@ -5351,7 +5395,7 @@ class TestSubnetsV2(NeutronDbPluginV2TestCase): self._test_list_resources('subnet', subnets) def test_list_subnets_shared(self): - with self.network(shared=True) as network: + with self.network(shared=True, as_admin=True) as network: with self.subnet(network=network, cidr='10.0.0.0/24') as subnet: with self.subnet(cidr='10.0.1.0/24') as priv_subnet: # normal user should see only 1 subnet @@ -6117,8 +6161,7 @@ class TestSubnetPoolsV2(NeutronDbPluginV2TestCase): min_prefixlen='24', shared=True) admin_res = self._list('subnetpools') - mortal_res = self._list('subnetpools', - neutron_context=context.Context('', 'not-the-owner')) + mortal_res = self._list('subnetpools', tenant_id='not-the-owner') self.assertEqual(1, len(admin_res['subnetpools'])) self.assertEqual(1, len(mortal_res['subnetpools'])) @@ -6130,8 +6173,7 @@ class TestSubnetPoolsV2(NeutronDbPluginV2TestCase): min_prefixlen='24', shared=False) admin_res = self._list('subnetpools') - mortal_res = self._list('subnetpools', - neutron_context=context.Context('', 'not-the-owner')) + mortal_res = self._list('subnetpools', tenant_id='not-the-owner') self.assertEqual(1, len(admin_res['subnetpools'])) self.assertEqual(0, len(mortal_res['subnetpools'])) @@ -6659,7 +6701,7 @@ class DbModelMixin(object): network_obj.NetworkRBAC( ctx, object_id=network.id, - action='access_as_shared', + action=rbac_db_models.ACCESS_SHARED, project_id=network.project_id, target_project='*').create() net2 = models_v2.Network(name="net_net2", status="OK", @@ -7066,7 +7108,8 @@ class NeutronDbPluginV2AsMixinTestCase(NeutronDbPluginV2TestCase, super(NeutronDbPluginV2AsMixinTestCase, self).setUp() self.plugin = importutils.import_object(DB_PLUGIN_KLASS) self.context = context.get_admin_context() - self.net_data = {'network': {'id': 'fake-id', + self.net_id = uuidutils.generate_uuid() + self.net_data = {'network': {'id': self.net_id, 'name': 'net1', 'admin_state_up': True, 'tenant_id': TEST_TENANT_ID, @@ -7075,7 +7118,7 @@ class NeutronDbPluginV2AsMixinTestCase(NeutronDbPluginV2TestCase, def test_create_network_with_default_status(self): net = self.plugin.create_network(self.context, self.net_data) default_net_create_status = 'ACTIVE' - expected = [('id', 'fake-id'), ('name', 'net1'), + expected = [('id', self.net_id), ('name', 'net1'), ('admin_state_up', True), ('tenant_id', TEST_TENANT_ID), ('shared', False), ('status', default_net_create_status)] for k, v in expected: @@ -7113,6 +7156,81 @@ class NeutronDbPluginV2AsMixinTestCase(NeutronDbPluginV2TestCase, new_subnetpool_id, None) + def test_create_subnet_invalid_network_mtu_ipv4_returns_409(self): + self.net_data['network']['mtu'] = common_constants.IPV4_MIN_MTU - 1 + net = self.plugin.create_network(self.context, self.net_data) + self._create_subnet(self.fmt, + net['id'], + '10.0.0.0/24', + webob.exc.HTTPConflict.code) + + def test_create_subnet_invalid_network_mtu_ipv6_returns_409(self): + self.net_data['network']['mtu'] = constants.IPV6_MIN_MTU - 1 + net = self.plugin.create_network(self.context, self.net_data) + self._create_subnet(self.fmt, + net['id'], + '2001:db8:0:1::/64', + webob.exc.HTTPConflict.code, + ip_version=constants.IP_VERSION_6) + + def test_update_network_invalid_mtu(self): + self.net_data['network']['mtu'] = 1500 + net = self.plugin.create_network(self.context, self.net_data) + + # This should succeed with no subnets + self.net_data['network']['mtu'] = common_constants.IPV4_MIN_MTU - 1 + self.plugin.update_network(self.context, net['id'], self.net_data) + + # reset mtu + self.net_data['network']['mtu'] = 1500 + self.plugin.update_network(self.context, net['id'], self.net_data) + + self._create_subnet(self.fmt, + net['id'], + '10.0.0.0/24', + ip_version=constants.IP_VERSION_4) + + # These should succeed with just an IPv4 subnet present + self.net_data['network']['mtu'] = constants.IPV6_MIN_MTU + self.plugin.update_network(self.context, net['id'], self.net_data) + self.net_data['network']['mtu'] = constants.IPV6_MIN_MTU - 1 + self.plugin.update_network(self.context, net['id'], self.net_data) + self.net_data['network']['mtu'] = common_constants.IPV4_MIN_MTU + self.plugin.update_network(self.context, net['id'], self.net_data) + + # This should fail with any subnets present + self.net_data['network']['mtu'] = common_constants.IPV4_MIN_MTU - 1 + with testlib_api.ExpectedException(mtu_exc.NetworkMTUSubnetConflict): + self.plugin.update_network(self.context, net['id'], self.net_data) + + def test_update_network_invalid_mtu_ipv4_ipv6(self): + self.net_data['network']['mtu'] = 1500 + net = self.plugin.create_network(self.context, self.net_data) + + self._create_subnet(self.fmt, + net['id'], + '10.0.0.0/24', + ip_version=constants.IP_VERSION_4) + self._create_subnet(self.fmt, + net['id'], + '2001:db8:0:1::/64', + ip_version=constants.IP_VERSION_6) + + # This should succeed with both subnets present + self.net_data['network']['mtu'] = constants.IPV6_MIN_MTU + self.plugin.update_network(self.context, net['id'], self.net_data) + + # These should all fail with both subnets present + with testlib_api.ExpectedException(mtu_exc.NetworkMTUSubnetConflict): + self.net_data['network']['mtu'] = constants.IPV6_MIN_MTU - 1 + self.plugin.update_network(self.context, net['id'], self.net_data) + with testlib_api.ExpectedException(mtu_exc.NetworkMTUSubnetConflict): + self.net_data['network']['mtu'] = common_constants.IPV4_MIN_MTU + self.plugin.update_network(self.context, net['id'], self.net_data) + with testlib_api.ExpectedException(mtu_exc.NetworkMTUSubnetConflict): + self.net_data['network']['mtu'] = common_constants.IPV4_MIN_MTU - 1 + self.plugin.update_network(self.context, net['id'], self.net_data) + class TestNetworks(testlib_api.SqlTestCase): def setUp(self): @@ -7197,10 +7315,10 @@ class DbOperationBoundMixin(object): def get_api_kwargs(self): context_ = self._get_context() - return {'set_context': True, 'tenant_id': context_.project_id} + return {'tenant_id': context_.project_id} def _list_and_record_queries(self, resource, query_params=None): - kwargs = {'neutron_context': self._get_context()} + kwargs = {} if query_params: kwargs['query_params'] = query_params # list once before tracking to flush out any quota recalculations. diff --git a/neutron/tests/unit/db/test_dvr_mac_db.py b/neutron/tests/unit/db/test_dvr_mac_db.py index 80d650a7d8..6f87672712 100644 --- a/neutron/tests/unit/db/test_dvr_mac_db.py +++ b/neutron/tests/unit/db/test_dvr_mac_db.py @@ -188,22 +188,28 @@ class DvrDbMixinTestCase(test_plugin.Ml2PluginV2TestCase): arg_list = (portbindings.HOST_ID,) with self.subnet() as subnet,\ self.port(subnet=subnet, + is_admin=True, device_owner=constants.DEVICE_OWNER_COMPUTE_PREFIX, arg_list=arg_list, **host_arg) as compute_port,\ self.port(subnet=subnet, device_owner=constants.DEVICE_OWNER_DHCP, + is_admin=True, arg_list=arg_list, **host_arg) as dhcp_port,\ self.port(subnet=subnet, device_owner=constants.DEVICE_OWNER_LOADBALANCER, + is_admin=True, arg_list=arg_list, **host_arg) as lb_port,\ self.port(device_owner=constants.DEVICE_OWNER_COMPUTE_PREFIX, + is_admin=True, arg_list=arg_list, **host_arg),\ self.port(subnet=subnet, device_owner=constants.DEVICE_OWNER_COMPUTE_PREFIX, + is_admin=True, arg_list=arg_list, **{portbindings.HOST_ID: 'other'}),\ self.port(subnet=subnet, device_owner=constants.DEVICE_OWNER_NETWORK_PREFIX, + is_admin=True, arg_list=arg_list, **host_arg): expected_ids = [port['port']['id'] for port in [compute_port, dhcp_port, lb_port]] diff --git a/neutron/tests/unit/db/test_ipam_backend_mixin.py b/neutron/tests/unit/db/test_ipam_backend_mixin.py index e81a908ec2..fa2872a317 100644 --- a/neutron/tests/unit/db/test_ipam_backend_mixin.py +++ b/neutron/tests/unit/db/test_ipam_backend_mixin.py @@ -373,7 +373,8 @@ class TestPortUpdateIpam(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): net_id=network['network']['id'], tenant_id=network['network']['tenant_id'], arg_list=(portbindings.HOST_ID,), - **{portbindings.HOST_ID: 'fakehost'}) + **{portbindings.HOST_ID: 'fakehost'}, + is_admin=True) port = self.deserialize(self.fmt, response) # Create the subnet and try to update the port to get an IP @@ -381,7 +382,8 @@ class TestPortUpdateIpam(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): data = {'port': { 'fixed_ips': [{'subnet_id': subnet['subnet']['id']}]}} port_id = port['port']['id'] - port_req = self.new_update_request('ports', data, port_id) + port_req = self.new_update_request('ports', data, port_id, + as_admin=True) response = port_req.get_response(self.api) res = self.deserialize(self.fmt, response) diff --git a/neutron/tests/unit/db/test_ipam_pluggable_backend.py b/neutron/tests/unit/db/test_ipam_pluggable_backend.py index b77ea16458..958c0abbc6 100644 --- a/neutron/tests/unit/db/test_ipam_pluggable_backend.py +++ b/neutron/tests/unit/db/test_ipam_pluggable_backend.py @@ -71,7 +71,6 @@ class TestDbBasePluginIpam(test_db_base.NeutronDbPluginV2TestCase): plugin = 'neutron.tests.unit.db.test_ipam_backend_mixin.TestPlugin' super(TestDbBasePluginIpam, self).setUp(plugin=plugin) cfg.CONF.set_override("ipam_driver", 'internal') - self.tenant_id = uuidutils.generate_uuid() self.subnet_id = uuidutils.generate_uuid() self.admin_context = ncontext.get_admin_context() @@ -89,7 +88,7 @@ class TestDbBasePluginIpam(test_db_base.NeutronDbPluginV2TestCase): 'device_owner': constants.DEVICE_OWNER_COMPUTE_PREFIX + 'None' }, 'subnet_request': ipam_req.SpecificSubnetRequest( - self.tenant_id, + self._tenant_id, self.subnet_id, '10.0.0.0/24', '10.0.0.1', diff --git a/neutron/tests/unit/db/test_l3_db.py b/neutron/tests/unit/db/test_l3_db.py index 9b65b60f09..43d4ec4a49 100644 --- a/neutron/tests/unit/db/test_l3_db.py +++ b/neutron/tests/unit/db/test_l3_db.py @@ -928,7 +928,8 @@ class L3TestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): with db_api.CONTEXT_WRITER.using(self.ctx): res = self._create_network( self.fmt, name, True, - arg_list=(extnet_apidef.EXTERNAL,), **kwargs) + arg_list=(extnet_apidef.EXTERNAL,), + as_admin=True, **kwargs) if res.status_int >= webob.exc.HTTPClientError.code: raise webob.exc.HTTPClientError(code=res.status_int) return self.deserialize(self.fmt, res) diff --git a/neutron/tests/unit/db/test_ovn_revision_numbers_db.py b/neutron/tests/unit/db/test_ovn_revision_numbers_db.py index 62dfc9caa1..f375d3602d 100644 --- a/neutron/tests/unit/db/test_ovn_revision_numbers_db.py +++ b/neutron/tests/unit/db/test_ovn_revision_numbers_db.py @@ -237,7 +237,7 @@ class TestRevisionNumberMaintenance(test_securitygroup.SecurityGroupsTestCase, '10.0.0.0/24')['subnet'] self._set_net_external(self.net['id']) info = {'network_id': self.net['id']} - router = self._make_router(self.fmt, None, + router = self._make_router(self.fmt, self._tenant_id, external_gateway_info=info)['router'] fip = self._make_floatingip(self.fmt, self.net['id'])['floatingip'] port = self._make_port(self.fmt, self.net['id'])['port'] diff --git a/neutron/tests/unit/db/test_rbac_db_mixin.py b/neutron/tests/unit/db/test_rbac_db_mixin.py index 755efa4f0f..e2a2e1ed10 100644 --- a/neutron/tests/unit/db/test_rbac_db_mixin.py +++ b/neutron/tests/unit/db/test_rbac_db_mixin.py @@ -34,7 +34,8 @@ class NetworkRbacTestcase(test_plugin.NeutronDbPluginV2TestCase): self.context = context.get_admin_context() super(NetworkRbacTestcase, self).setUp(plugin='ml2') - def _make_networkrbac(self, network, target, action='access_as_shared'): + def _make_networkrbac(self, network, target, + action=rbac_db_models.ACCESS_SHARED): policy = { 'rbac_policy': {'project_id': network['network']['project_id'], 'object_id': network['network']['id'], @@ -71,7 +72,7 @@ class NetworkRbacTestcase(test_plugin.NeutronDbPluginV2TestCase): self._assert_external_net_state(net_id, is_external=False) policy = self._make_networkrbac(ext_net, '*', - 'access_as_external') + rbac_db_models.ACCESS_EXTERNAL) self.plugin.create_rbac_policy(self.context, policy) self._assert_external_net_state(net_id, is_external=True) @@ -96,7 +97,7 @@ class NetworkRbacTestcase(test_plugin.NeutronDbPluginV2TestCase): with self.network() as ext_net: policy = self._make_networkrbac(ext_net, orig_target, - 'access_as_external') + rbac_db_models.ACCESS_EXTERNAL) netrbac = self.plugin.create_rbac_policy(self.context, policy) update_policy = {'rbac_policy': {'target_project': new_target}} @@ -114,7 +115,7 @@ class NetworkRbacTestcase(test_plugin.NeutronDbPluginV2TestCase): self._assert_external_net_state(net_id, is_external=False) policy = self._make_networkrbac(ext_net, '*', - 'access_as_external') + rbac_db_models.ACCESS_EXTERNAL) net_rbac = self.plugin.create_rbac_policy(self.context, policy) self._assert_external_net_state(net_id, is_external=True) self.plugin.delete_rbac_policy(self.context, net_rbac['id']) @@ -126,12 +127,12 @@ class NetworkRbacTestcase(test_plugin.NeutronDbPluginV2TestCase): self._assert_external_net_state(net_id, is_external=False) policy1 = self._make_networkrbac(ext_net, 'test-tenant-1', - 'access_as_external') + rbac_db_models.ACCESS_EXTERNAL) net_rbac1 = self.plugin.create_rbac_policy(self.context, policy1) self._assert_external_net_state(net_id, is_external=True) policy2 = self._make_networkrbac(ext_net, 'test-tenant-2', - 'access_as_external') + rbac_db_models.ACCESS_EXTERNAL) self.plugin.create_rbac_policy(self.context, policy2) self._assert_external_net_state(net_id, is_external=True) self.plugin.delete_rbac_policy(self.context, net_rbac1['id']) diff --git a/neutron/tests/unit/db/test_securitygroups_db.py b/neutron/tests/unit/db/test_securitygroups_db.py index 593272027b..9036a11e9d 100644 --- a/neutron/tests/unit/db/test_securitygroups_db.py +++ b/neutron/tests/unit/db/test_securitygroups_db.py @@ -404,6 +404,38 @@ class SecurityGroupDbMixinTestCase(testlib_api.SqlTestCase): self.assertEqual([mock.ANY, mock.ANY], payload.metadata.get('security_group_rule_ids')) + def test_security_group_rule_after_delete_event_for_remot_group(self): + sg1_dict = self.mixin.create_security_group(self.ctx, FAKE_SECGROUP) + sg2_dict = self.mixin.create_security_group(self.ctx, FAKE_SECGROUP) + + fake_rule = copy.deepcopy(FAKE_SECGROUP_RULE) + fake_rule['security_group_rule']['security_group_id'] = sg1_dict['id'] + fake_rule['security_group_rule']['remote_group_id'] = sg2_dict['id'] + fake_rule['security_group_rule']['remote_ip_prefix'] = None + remote_rule = self.mixin.create_security_group_rule( + self.ctx, fake_rule) + + with mock.patch.object(registry, "publish") as mock_publish: + self.mixin.delete_security_group(self.ctx, sg2_dict['id']) + mock_publish.assert_has_calls( + [mock.call('security_group', 'before_delete', + mock.ANY, payload=mock.ANY), + mock.call('security_group', 'precommit_delete', + mock.ANY, + payload=mock.ANY), + mock.call('security_group', 'after_delete', + mock.ANY, + payload=mock.ANY), + mock.call('security_group_rule', 'after_delete', + mock.ANY, + payload=mock.ANY)]) + rule_payload = mock_publish.mock_calls[3][2]['payload'] + self.assertEqual(remote_rule['id'], rule_payload.resource_id) + self.assertEqual(sg1_dict['id'], + rule_payload.metadata['security_group_id']) + self.assertEqual(sg2_dict['id'], + rule_payload.metadata['remote_group_id']) + def test_security_group_rule_precommit_create_event_fail(self): registry.subscribe(fake_callback, resources.SECURITY_GROUP_RULE, events.PRECOMMIT_CREATE) diff --git a/neutron/tests/unit/debug/test_commands.py b/neutron/tests/unit/debug/test_commands.py deleted file mode 100644 index 74bf392999..0000000000 --- a/neutron/tests/unit/debug/test_commands.py +++ /dev/null @@ -1,325 +0,0 @@ -# Copyright 2012, Nachi Ueno, NTT MCL, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import socket -from unittest import mock - -from neutron_lib.api.definitions import portbindings -from neutron_lib import constants -from oslo_config import cfg - -from neutron.agent.linux import interface -from neutron.common import config as common_config -from neutron.conf.agent import common as config -from neutron.debug import commands -from neutron.debug import debug_agent -from neutron.tests import base - - -class MyApp(object): - def __init__(self, _stdout): - self.stdout = _stdout - - -class TestDebugCommands(base.BaseTestCase): - def setUp(self): - super(TestDebugCommands, self).setUp() - config.register_interface_opts() - common_config.init([]) - config.register_interface_driver_opts_helper(cfg.CONF) - - device_exists_p = mock.patch( - 'neutron.agent.linux.ip_lib.device_exists', return_value=False) - device_exists_p.start() - namespace_e_p = mock.patch( - 'neutron.agent.linux.ip_lib.network_namespace_exists') - namespace_e_p.start() - namespace_d_p = mock.patch( - 'neutron.agent.linux.ip_lib.delete_network_namespace') - namespace_d_p.start() - ensure_namespace_p = mock.patch( - 'neutron.agent.linux.ip_lib.IPWrapper.ensure_namespace') - ensure_namespace_p.start() - dvr_cls_p = mock.patch('neutron.agent.linux.interface.NullDriver') - driver_cls = dvr_cls_p.start() - mock_driver = mock.MagicMock() - mock_driver.DEV_NAME_LEN = ( - interface.LinuxInterfaceDriver.DEV_NAME_LEN) - mock_driver.get_device_name.return_value = 'tap12345678-12' - driver_cls.return_value = mock_driver - self.driver = mock_driver - - client_cls_p = mock.patch('neutronclient.v2_0.client.Client') - client_cls = client_cls_p.start() - client_inst = mock.Mock() - client_cls.return_value = client_inst - - fake_network = {'network': {'id': 'fake_net', - 'tenant_id': 'fake_tenant', - 'subnets': ['fake_subnet']}} - fake_port = {'port': - {'id': 'fake_port', - 'device_owner': 'fake_device', - 'mac_address': 'aa:bb:cc:dd:ee:ffa', - 'network_id': 'fake_net', - 'fixed_ips': - [{'subnet_id': 'fake_subnet', 'ip_address': '10.0.0.3'}] - }} - fake_ports = {'ports': [fake_port['port']]} - self.fake_ports = fake_ports - allocation_pools = [{'start': '10.0.0.2', - 'end': '10.0.0.254'}] - fake_subnet_v4 = {'subnet': {'name': 'fake_subnet_v4', - 'id': 'fake_subnet', - 'network_id': 'fake_net', - 'gateway_ip': '10.0.0.1', - 'dns_nameservers': ['10.0.0.2'], - 'host_routes': [], - 'cidr': '10.0.0.0/24', - 'allocation_pools': allocation_pools, - 'enable_dhcp': True, - 'ip_version': constants.IP_VERSION_4}} - - client_inst.list_ports.return_value = fake_ports - client_inst.create_port.return_value = fake_port - client_inst.show_port.return_value = fake_port - client_inst.show_network.return_value = fake_network - client_inst.show_subnet.return_value = fake_subnet_v4 - self.client = client_inst - mock_std = mock.Mock() - self.app = MyApp(mock_std) - self.app.debug_agent = debug_agent.NeutronDebugAgent(cfg.CONF, - client_inst, - mock_driver) - - def _test_create_probe(self, device_owner): - cmd = commands.CreateProbe(self.app, None) - cmd_parser = cmd.get_parser('create_probe') - if device_owner == debug_agent.DEVICE_OWNER_COMPUTE_PROBE: - args = ['fake_net', '--device-owner', 'compute'] - else: - args = ['fake_net'] - parsed_args = cmd_parser.parse_args(args) - cmd.run(parsed_args) - fake_port = {'port': - {'device_owner': device_owner, - 'admin_state_up': True, - 'network_id': 'fake_net', - 'tenant_id': 'fake_tenant', - portbindings.HOST_ID: cfg.CONF.host, - 'fixed_ips': [{'subnet_id': 'fake_subnet'}], - 'device_id': socket.gethostname()}} - namespace = 'qprobe-fake_port' - self.client.assert_has_calls([mock.call.show_network('fake_net'), - mock.call.show_subnet('fake_subnet'), - mock.call.create_port(fake_port), - mock.call.show_subnet('fake_subnet')]) - self.driver.assert_has_calls([mock.call.get_device_name(mock.ANY), - mock.call.plug('fake_net', - 'fake_port', - 'tap12345678-12', - 'aa:bb:cc:dd:ee:ffa', - namespace=namespace), - mock.call.init_l3('tap12345678-12', - ['10.0.0.3/24'], - namespace=namespace - )]) - - def test_create_network_probe(self): - self._test_create_probe(debug_agent.DEVICE_OWNER_NETWORK_PROBE) - - def test_create_nova_probe(self): - self._test_create_probe(debug_agent.DEVICE_OWNER_COMPUTE_PROBE) - - def _test_create_probe_external(self, device_owner): - fake_network = {'network': {'id': 'fake_net', - 'tenant_id': 'fake_tenant', - 'router:external': True, - 'subnets': ['fake_subnet']}} - self.client.show_network.return_value = fake_network - cmd = commands.CreateProbe(self.app, None) - cmd_parser = cmd.get_parser('create_probe') - if device_owner == debug_agent.DEVICE_OWNER_COMPUTE_PROBE: - args = ['fake_net', '--device-owner', 'compute'] - else: - args = ['fake_net'] - parsed_args = cmd_parser.parse_args(args) - cmd.run(parsed_args) - fake_port = {'port': - {'device_owner': device_owner, - 'admin_state_up': True, - 'network_id': 'fake_net', - 'tenant_id': 'fake_tenant', - portbindings.HOST_ID: cfg.CONF.host, - 'fixed_ips': [{'subnet_id': 'fake_subnet'}], - 'device_id': socket.gethostname()}} - namespace = 'qprobe-fake_port' - self.client.assert_has_calls([mock.call.show_network('fake_net'), - mock.call.show_subnet('fake_subnet'), - mock.call.create_port(fake_port), - mock.call.show_subnet('fake_subnet')]) - self.driver.assert_has_calls([mock.call.get_device_name(mock.ANY), - mock.call.plug('fake_net', - 'fake_port', - 'tap12345678-12', - 'aa:bb:cc:dd:ee:ffa', - namespace=namespace), - mock.call.init_l3('tap12345678-12', - ['10.0.0.3/24'], - namespace=namespace - )]) - - def test_create_network_probe_external(self): - self._test_create_probe_external( - debug_agent.DEVICE_OWNER_NETWORK_PROBE) - - def test_create_nova_probe_external(self): - self._test_create_probe_external( - debug_agent.DEVICE_OWNER_COMPUTE_PROBE) - - def test_delete_probe(self): - cmd = commands.DeleteProbe(self.app, None) - cmd_parser = cmd.get_parser('delete_probe') - args = ['fake_port'] - parsed_args = cmd_parser.parse_args(args) - cmd.run(parsed_args) - namespace = 'qprobe-fake_port' - self.client.assert_has_calls([mock.call.show_port('fake_port'), - mock.call.delete_port('fake_port')]) - self.driver.assert_has_calls([mock.call.get_device_name(mock.ANY), - mock.call.unplug('tap12345678-12', - namespace=namespace)]) - - def test_delete_probe_external(self): - fake_network = {'network': {'id': 'fake_net', - 'tenant_id': 'fake_tenant', - 'router:external': True, - 'subnets': ['fake_subnet']}} - self.client.show_network.return_value = fake_network - cmd = commands.DeleteProbe(self.app, None) - cmd_parser = cmd.get_parser('delete_probe') - args = ['fake_port'] - parsed_args = cmd_parser.parse_args(args) - cmd.run(parsed_args) - namespace = 'qprobe-fake_port' - self.client.assert_has_calls([mock.call.show_port('fake_port'), - mock.call.delete_port('fake_port')]) - self.driver.assert_has_calls([mock.call.get_device_name(mock.ANY), - mock.call.unplug('tap12345678-12', - namespace=namespace)]) - - def test_list_probe(self): - cmd = commands.ListProbe(self.app, None) - cmd_parser = cmd.get_parser('list_probe') - args = [] - parsed_args = cmd_parser.parse_args(args) - cmd.run(parsed_args) - self.client.assert_has_calls( - [mock.call.list_ports( - device_owner=[debug_agent.DEVICE_OWNER_NETWORK_PROBE, - debug_agent.DEVICE_OWNER_COMPUTE_PROBE])]) - - def test_exec_command(self): - cmd = commands.ExecProbe(self.app, None) - cmd_parser = cmd.get_parser('exec_command') - args = ['fake_port', 'fake_command'] - parsed_args = cmd_parser.parse_args(args) - with mock.patch('neutron.agent.linux.ip_lib.IpNetnsCommand') as ns: - cmd.run(parsed_args) - ns.assert_has_calls([mock.call.execute(mock.ANY)]) - self.client.assert_has_calls([mock.call.show_port('fake_port')]) - - def test_clear_probe(self): - cmd = commands.ClearProbe(self.app, None) - cmd_parser = cmd.get_parser('clear_probe') - args = [] - parsed_args = cmd_parser.parse_args(args) - cmd.run(parsed_args) - namespace = 'qprobe-fake_port' - self.client.assert_has_calls( - [mock.call.list_ports( - device_id=socket.gethostname(), - device_owner=[debug_agent.DEVICE_OWNER_NETWORK_PROBE, - debug_agent.DEVICE_OWNER_COMPUTE_PROBE]), - mock.call.show_port('fake_port'), - mock.call.delete_port('fake_port')]) - self.driver.assert_has_calls([mock.call.get_device_name(mock.ANY), - mock.call.unplug('tap12345678-12', - namespace=namespace)]) - - def test_ping_all_with_ensure_port(self): - fake_ports = self.fake_ports - - def fake_port_list(network_id=None, device_owner=None, device_id=None): - if network_id: - # In order to test ensure_port, return [] - return {'ports': []} - return fake_ports - self.client.list_ports.side_effect = fake_port_list - cmd = commands.PingAll(self.app, None) - cmd_parser = cmd.get_parser('ping_all') - args = [] - parsed_args = cmd_parser.parse_args(args) - namespace = 'qprobe-fake_port' - with mock.patch('neutron.agent.linux.ip_lib.IpNetnsCommand') as ns: - cmd.run(parsed_args) - ns.assert_has_calls([mock.call.execute(mock.ANY)]) - fake_port = {'port': - {'device_owner': debug_agent.DEVICE_OWNER_NETWORK_PROBE, - 'admin_state_up': True, - 'network_id': 'fake_net', - 'tenant_id': 'fake_tenant', - portbindings.HOST_ID: cfg.CONF.host, - 'fixed_ips': [{'subnet_id': 'fake_subnet'}], - 'device_id': socket.gethostname()}} - expected = [mock.call.show_network('fake_net'), - mock.call.show_subnet('fake_subnet'), - mock.call.create_port(fake_port), - mock.call.show_subnet('fake_subnet')] - self.client.assert_has_calls(expected) - self.driver.assert_has_calls([mock.call.init_l3('tap12345678-12', - ['10.0.0.3/24'], - namespace=namespace - )]) - - def test_ping_all(self): - cmd = commands.PingAll(self.app, None) - cmd_parser = cmd.get_parser('ping_all') - args = [] - parsed_args = cmd_parser.parse_args(args) - with mock.patch('neutron.agent.linux.ip_lib.IpNetnsCommand') as ns: - cmd.run(parsed_args) - ns.assert_has_calls([mock.call.execute(mock.ANY)]) - expected = [mock.call.list_ports(), - mock.call.list_ports( - network_id='fake_net', - device_owner=debug_agent.DEVICE_OWNER_NETWORK_PROBE, - device_id=socket.gethostname()), - mock.call.show_subnet('fake_subnet'), - mock.call.show_port('fake_port')] - self.client.assert_has_calls(expected) - - def test_ping_all_v6(self): - fake_subnet_v6 = {'subnet': {'name': 'fake_v6', - 'ip_version': constants.IP_VERSION_6}} - self.client.show_subnet.return_value = fake_subnet_v6 - cmd = commands.PingAll(self.app, None) - cmd_parser = cmd.get_parser('ping_all') - args = [] - parsed_args = cmd_parser.parse_args(args) - with mock.patch('neutron.agent.linux.ip_lib.IpNetnsCommand') as ns: - cmd.run(parsed_args) - ns.assert_has_calls([mock.call.execute(mock.ANY)]) - self.client.assert_has_calls([mock.call.list_ports()]) diff --git a/neutron/tests/unit/extensions/test_address_group.py b/neutron/tests/unit/extensions/test_address_group.py index ff37ba684f..e3339b0320 100644 --- a/neutron/tests/unit/extensions/test_address_group.py +++ b/neutron/tests/unit/extensions/test_address_group.py @@ -84,9 +84,8 @@ class AddressGroupTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): def _test_address_group_actions(self, addr_group_id, data, action, expected=None, tenant_id=None): act_req = self.new_action_request( - 'address-groups', data, addr_group_id, action) - act_req.environ['neutron.context'] = context.Context( - '', tenant_id or self._tenant_id) + 'address-groups', data, addr_group_id, action, + tenant_id=tenant_id or self._tenant_id) act_res = act_req.get_response(self.ext_api) if expected: diff --git a/neutron/tests/unit/extensions/test_address_scope.py b/neutron/tests/unit/extensions/test_address_scope.py index 6d5eb30031..7e33980686 100644 --- a/neutron/tests/unit/extensions/test_address_scope.py +++ b/neutron/tests/unit/extensions/test_address_scope.py @@ -49,39 +49,40 @@ class AddressScopeTestExtensionManager(object): class AddressScopeTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): def _create_address_scope(self, fmt, ip_version=constants.IP_VERSION_4, - expected_res_status=None, admin=False, **kwargs): + expected_res_status=None, admin=False, + tenant_id=None, **kwargs): address_scope = {'address_scope': {}} address_scope['address_scope']['ip_version'] = ip_version + tenant_id = tenant_id or self._tenant_id for k, v in kwargs.items(): address_scope['address_scope'][k] = str(v) address_scope_req = self.new_create_request('address-scopes', - address_scope, fmt) - - if not admin: - neutron_context = context.Context('', kwargs.get('tenant_id', - self._tenant_id)) - address_scope_req.environ['neutron.context'] = neutron_context + address_scope, fmt, + tenant_id=tenant_id, + as_admin=admin) address_scope_res = address_scope_req.get_response(self.ext_api) if expected_res_status: self.assertEqual(expected_res_status, address_scope_res.status_int) return address_scope_res - def _make_address_scope(self, fmt, ip_version, admin=False, **kwargs): + def _make_address_scope(self, fmt, ip_version, admin=False, tenant_id=None, + **kwargs): res = self._create_address_scope(fmt, ip_version, - admin=admin, **kwargs) + admin=admin, tenant_id=tenant_id, + **kwargs) if res.status_int >= webob.exc.HTTPClientError.code: raise webob.exc.HTTPClientError(code=res.status_int) return self.deserialize(fmt, res) @contextlib.contextmanager def address_scope(self, ip_version=constants.IP_VERSION_4, - admin=False, **kwargs): - if 'project_id' in kwargs: - kwargs['tenant_id'] = kwargs['project_id'] + admin=False, tenant_id=None, **kwargs): + tenant_id = tenant_id if tenant_id else kwargs.pop( + 'tenant_id', None) addr_scope = self._make_address_scope(self.fmt, ip_version, - admin, **kwargs) + admin, tenant_id, **kwargs) yield addr_scope def _test_create_address_scope(self, ip_version=constants.IP_VERSION_4, @@ -99,9 +100,9 @@ class AddressScopeTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): def _test_update_address_scope(self, addr_scope_id, data, admin=False, expected=None, tenant_id=None): update_req = self.new_update_request( - 'address-scopes', data, addr_scope_id) - update_req.environ['neutron.context'] = context.Context( - '', tenant_id or self._tenant_id, is_admin=admin) + 'address-scopes', data, addr_scope_id, + tenant_id=tenant_id or self._tenant_id, + as_admin=admin) update_res = update_req.get_response(self.ext_api) if expected: @@ -244,8 +245,7 @@ class TestAddressScope(AddressScopeTestCase): admin=True) admin_res = self._list('address-scopes') mortal_res = self._list( - 'address-scopes', - neutron_context=context.Context('', 'not-the-owner')) + 'address-scopes', tenant_id='not-the-owner') self.assertEqual(1, len(admin_res['address_scopes'])) self.assertEqual(1, len(mortal_res['address_scopes'])) @@ -254,8 +254,7 @@ class TestAddressScope(AddressScopeTestCase): name='foo-address-scope') admin_res = self._list('address-scopes') mortal_res = self._list( - 'address-scopes', - neutron_context=context.Context('', 'not-the-owner')) + 'address-scopes', tenant_id='not-the-owner') self.assertEqual(1, len(admin_res['address_scopes'])) self.assertEqual(0, len(mortal_res['address_scopes'])) diff --git a/neutron/tests/unit/extensions/test_agent.py b/neutron/tests/unit/extensions/test_agent.py index 2a084bf4dd..0cb1cb7037 100644 --- a/neutron/tests/unit/extensions/test_agent.py +++ b/neutron/tests/unit/extensions/test_agent.py @@ -59,11 +59,10 @@ class TestAgentPlugin(db_base_plugin_v2.NeutronDbPluginV2, class AgentDBTestMixIn(object): def _list_agents(self, expected_res_status=None, - neutron_context=None, query_string=None): agent_res = self._list('agents', - neutron_context=neutron_context, - query_params=query_string) + query_params=query_string, + as_admin=True) if expected_res_status: self.assertEqual(expected_res_status, agent_res.status_int) return agent_res @@ -107,14 +106,12 @@ class AgentDBTestCase(AgentDBTestMixIn, def test_create_agent(self): data = {'agent': {}} _req = self.new_create_request('agents', data, self.fmt) - _req.environ['neutron.context'] = context.Context( - '', 'tenant_id') res = _req.get_response(self.ext_api) self.assertEqual(exc.HTTPBadRequest.code, res.status_int) def test_list_agent(self): agents = self._register_agent_states() - res = self._list('agents') + res = self._list('agents', as_admin=True) self.assertEqual(len(agents), len(res['agents'])) def test_show_agent(self): @@ -122,7 +119,7 @@ class AgentDBTestCase(AgentDBTestMixIn, agents = self._list_agents( query_string='binary=' + constants.AGENT_PROCESS_L3) self.assertEqual(2, len(agents['agents'])) - agent = self._show('agents', agents['agents'][0]['id']) + agent = self._show('agents', agents['agents'][0]['id'], as_admin=True) self.assertEqual(constants.AGENT_PROCESS_L3, agent['agent']['binary']) def test_update_agent(self): @@ -132,13 +129,13 @@ class AgentDBTestCase(AgentDBTestMixIn, '&host=' + L3_HOSTB)) self.assertEqual(1, len(agents['agents'])) com_id = agents['agents'][0]['id'] - agent = self._show('agents', com_id) + agent = self._show('agents', com_id, as_admin=True) new_agent = {} new_agent['agent'] = {} new_agent['agent']['admin_state_up'] = False new_agent['agent']['description'] = 'description' - self._update('agents', com_id, new_agent) - agent = self._show('agents', com_id) + self._update('agents', com_id, new_agent, as_admin=True) + agent = self._show('agents', com_id, as_admin=True) self.assertFalse(agent['agent']['admin_state_up']) self.assertEqual('description', agent['agent']['description']) diff --git a/neutron/tests/unit/extensions/test_availability_zone.py b/neutron/tests/unit/extensions/test_availability_zone.py index 78534c541f..e00054a026 100644 --- a/neutron/tests/unit/extensions/test_availability_zone.py +++ b/neutron/tests/unit/extensions/test_availability_zone.py @@ -71,12 +71,11 @@ class TestAZAgentCase(AZTestCommon): {'name': 'nova2', 'resource': 'network', 'state': 'available'}, {'name': 'nova2', 'resource': 'router', 'state': 'available'}, {'name': 'nova3', 'resource': 'router', 'state': 'unavailable'}] - res = self._list('availability_zones') + res = self._list('availability_zones', as_admin=True) azs = res['availability_zones'] self.assertCountEqual(expected, azs) # not admin case - ctx = context.Context('', 'noadmin') - res = self._list('availability_zones', neutron_context=ctx) + res = self._list('availability_zones', as_admin=False) azs = res['availability_zones'] self.assertCountEqual(expected, azs) @@ -89,33 +88,37 @@ class TestAZAgentCase(AZTestCommon): {'name': 'nova2', 'resource': 'network', 'state': 'available'}, {'name': 'nova2', 'resource': 'router', 'state': 'available'}, {'name': 'nova3', 'resource': 'router', 'state': 'unavailable'}] - res = self._list('availability_zones') + res = self._list('availability_zones', as_admin=True) azs = res['availability_zones'] self.assertCountEqual(expected, azs) # list with filter of 'name' res = self._list('availability_zones', - query_params="name=nova1") + query_params="name=nova1", + as_admin=True) azs = res['availability_zones'] self.assertCountEqual(expected[:1], azs) # list with filter of 'resource' res = self._list('availability_zones', - query_params="resource=router") + query_params="resource=router", + as_admin=True) azs = res['availability_zones'] self.assertCountEqual(expected[-2:], azs) # list with filter of 'state' as 'available' res = self._list('availability_zones', - query_params="state=available") + query_params="state=available", + as_admin=True) azs = res['availability_zones'] self.assertCountEqual(expected[:3], azs) # list with filter of 'state' as 'unavailable' res = self._list('availability_zones', - query_params="state=unavailable") + query_params="state=unavailable", + as_admin=True) azs = res['availability_zones'] self.assertCountEqual(expected[-1:], azs) def test_list_agent_with_az(self): helpers.register_dhcp_agent(host='host1', az='nova1') - res = self._list('agents') + res = self._list('agents', as_admin=True) self.assertEqual('nova1', res['agents'][0]['availability_zone']) diff --git a/neutron/tests/unit/extensions/test_data_plane_status.py b/neutron/tests/unit/extensions/test_data_plane_status.py index a6c99f1b77..f48752c7be 100644 --- a/neutron/tests/unit/extensions/test_data_plane_status.py +++ b/neutron/tests/unit/extensions/test_data_plane_status.py @@ -80,7 +80,8 @@ class DataPlaneStatusExtensionTestCase( data = {'port': {'data_plane_status': constants.ACTIVE}} req = self.new_update_request(port_def.COLLECTION_NAME, data, - port['port']['id']) + port['port']['id'], + as_admin=True) res = req.get_response(self.api) p = self.deserialize(self.fmt, res)['port'] self.assertEqual(200, res.status_code) @@ -106,9 +107,11 @@ class DataPlaneStatusExtensionTestCase( with self.port(name='port1') as port: res = self._update(port_def.COLLECTION_NAME, port['port']['id'], {'port': {dps_lib.DATA_PLANE_STATUS: - constants.ACTIVE}}) + constants.ACTIVE}}, + as_admin=True) res = self._update(port_def.COLLECTION_NAME, port['port']['id'], - {'port': {'name': 'port2'}}) + {'port': {'name': 'port2'}}, + as_admin=True) self.assertEqual(res['port']['name'], 'port2') self.assertEqual(res['port'][dps_lib.DATA_PLANE_STATUS], constants.ACTIVE) @@ -125,7 +128,8 @@ class DataPlaneStatusExtensionTestCase( with self.port(name='port1') as port: self._update(port_def.COLLECTION_NAME, port['port']['id'], {'port': {dps_lib.DATA_PLANE_STATUS: - constants.ACTIVE}}) + constants.ACTIVE}}, + as_admin=True) notify = set(n['event_type'] for n in fake_notifier.NOTIFICATIONS) duplicated_notify = expect_notify & notify self.assertEqual(expect_notify, duplicated_notify) diff --git a/neutron/tests/unit/extensions/test_default_subnetpools.py b/neutron/tests/unit/extensions/test_default_subnetpools.py index b089cdc4ad..c0fb2e1bec 100644 --- a/neutron/tests/unit/extensions/test_default_subnetpools.py +++ b/neutron/tests/unit/extensions/test_default_subnetpools.py @@ -71,9 +71,13 @@ class DefaultSubnetpoolsExtensionTestCase( return self.deserialize(self.fmt, res)['subnet'] - def _update_subnetpool(self, subnetpool_id, **data): + def _update_subnetpool(self, subnetpool_id, tenant_id=None, + as_admin=False, **data): + if 'shared' in data or 'is_default' in data: + as_admin = True update_req = self.new_update_request( - 'subnetpools', {'subnetpool': data}, subnetpool_id) + 'subnetpools', {'subnetpool': data}, subnetpool_id, + tenant_id=tenant_id, as_admin=as_admin) res = update_req.get_response(self.api) return self.deserialize(self.fmt, res)['subnetpool'] diff --git a/neutron/tests/unit/extensions/test_dns.py b/neutron/tests/unit/extensions/test_dns.py index 34d8f76c98..aca700c94e 100644 --- a/neutron/tests/unit/extensions/test_dns.py +++ b/neutron/tests/unit/extensions/test_dns.py @@ -109,10 +109,8 @@ class DnsExtensionTestCase(test_plugin.Ml2PluginV2TestCase): self.assertEqual(expected_res_status, port_res.status_int) return port_res - def _test_list_resources(self, resource, items, neutron_context=None, - query_params=None): + def _test_list_resources(self, resource, items, query_params=None): res = self._list('%ss' % resource, - neutron_context=neutron_context, query_params=query_params) resource = resource.replace('-', '_') self.assertCountEqual([i['id'] for i in res['%ss' % resource]], diff --git a/neutron/tests/unit/extensions/test_expose_port_forwarding_in_fip.py b/neutron/tests/unit/extensions/test_expose_port_forwarding_in_fip.py index 7b2561b53b..f11d8c03bb 100644 --- a/neutron/tests/unit/extensions/test_expose_port_forwarding_in_fip.py +++ b/neutron/tests/unit/extensions/test_expose_port_forwarding_in_fip.py @@ -112,7 +112,8 @@ class TestExtendFipPortForwardingExtension( ctx = context.get_admin_context() kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - with self.network(**kwargs) as extnet, self.network() as innet: + with self.network(as_admin=True, **kwargs) as extnet, \ + self.network() as innet: with self.subnet(network=extnet, cidr='200.0.0.0/22'), \ self.subnet(network=innet, cidr='10.0.0.0/24') as insub, \ self.router() as router: @@ -148,7 +149,8 @@ class TestExtendFipPortForwardingExtension( ctx = context.get_admin_context() kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - with self.network(**kwargs) as extnet, self.network() as innet: + with self.network(as_admin=True, **kwargs) as extnet,\ + self.network() as innet: with self.subnet(network=extnet, cidr='200.0.0.0/22'),\ self.subnet(network=innet, cidr='10.0.0.0/24') as insub,\ self.router() as router: @@ -241,7 +243,8 @@ class TestExtendFipPortForwardingExtension( ctx = context.get_admin_context() kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - with self.network(**kwargs) as extnet, self.network() as innet: + with self.network(as_admin=True, **kwargs) as extnet,\ + self.network() as innet: with self.subnet(network=extnet, cidr='200.0.0.0/22'),\ self.subnet(network=innet, cidr='10.0.0.0/24') as insub,\ self.subnet(network=innet, cidr='10.0.8.0/24') as insub2,\ @@ -317,10 +320,11 @@ class TestExtendFipPortForwardingExtension( ctx = context.get_admin_context() kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - with self.network(**kwargs) as extnet, self.network() as innet: + with self.network(as_admin=True, **kwargs) as extnet,\ + self.network() as innet: with self.subnet(network=extnet, cidr='200.0.0.0/22'),\ self.subnet(network=innet, cidr='10.0.0.0/24') as insub,\ - self.router(distributed=True) as router: + self.router(distributed=True, as_admin=True) as router: fip = self._make_floatingip(self.fmt, extnet['network']['id']) # check the floatingip response contains port_forwarding field self.assertIn(apidef.COLLECTION_NAME, fip['floatingip']) diff --git a/neutron/tests/unit/extensions/test_external_net.py b/neutron/tests/unit/extensions/test_external_net.py index edc76a2dbe..6e22ab658a 100644 --- a/neutron/tests/unit/extensions/test_external_net.py +++ b/neutron/tests/unit/extensions/test_external_net.py @@ -65,7 +65,8 @@ class ExtNetDBTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): def _set_net_external(self, net_id): self._update('networks', net_id, - {'network': {extnet_apidef.EXTERNAL: True}}) + {'network': {extnet_apidef.EXTERNAL: True}}, + as_admin=True) def test_list_nets_external(self): with self.network() as n1: @@ -111,13 +112,14 @@ class ExtNetDBTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): data = {'network': {'router:external': True}} req = self.new_update_request('networks', data, - network['network']['id']) - req.environ['neutron.context'] = context.Context('', 'noadmin') + network['network']['id'], + tenant_id='noadmin') res = req.get_response(self.api) self.assertEqual(exc.HTTPForbidden.code, res.status_int) def test_update_network_external_net_with_ports_set_not_shared(self): - with self.network(router__external=True, shared=True) as ext_net,\ + with self.network(router__external=True, shared=True, + as_admin=True) as ext_net,\ self.subnet(network=ext_net) as ext_subnet, \ self.port(subnet=ext_subnet, tenant_id='', @@ -125,7 +127,8 @@ class ExtNetDBTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): data = {'network': {'shared': False}} req = self.new_update_request('networks', data, - ext_net['network']['id']) + ext_net['network']['id'], + as_admin=True) res = req.get_response(self.api) self.assertEqual(exc.HTTPOk.code, res.status_int) ctx = context.Context(None, None, is_admin=True) @@ -158,18 +161,18 @@ class ExtNetDBTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): self.assertEqual(conditions.__str__(), "%s OR %s" % (txt, txt2)) def test_create_port_external_network_non_admin_fails(self): - with self.network(router__external=True) as ext_net: + with self.network(as_admin=True, router__external=True) as ext_net: with self.subnet(network=ext_net) as ext_subnet: with testtools.ExpectedException( exc.HTTPClientError) as ctx_manager: with self.port(subnet=ext_subnet, - set_context='True', + is_admin=False, tenant_id='noadmin'): pass self.assertEqual(403, ctx_manager.exception.code) def test_create_port_external_network_admin_succeeds(self): - with self.network(router__external=True) as ext_net: + with self.network(router__external=True, as_admin=True) as ext_net: with self.subnet(network=ext_net) as ext_subnet: with self.port(subnet=ext_subnet) as port: self.assertEqual(port['port']['network_id'], @@ -178,13 +181,13 @@ class ExtNetDBTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): def test_create_external_network_non_admin_fails(self): with testtools.ExpectedException(exc.HTTPClientError) as ctx_manager: with self.network(router__external=True, - set_context='True', + as_admin=False, tenant_id='noadmin'): pass self.assertEqual(403, ctx_manager.exception.code) def test_create_external_network_admin_succeeds(self): - with self.network(router__external=True) as ext_net: + with self.network(router__external=True, as_admin=True) as ext_net: self.assertTrue(ext_net['network'][extnet_apidef.EXTERNAL]) def test_delete_network_check_disassociated_floatingips(self): diff --git a/neutron/tests/unit/extensions/test_extraroute.py b/neutron/tests/unit/extensions/test_extraroute.py index 4e6b948dbd..48866e2f42 100644 --- a/neutron/tests/unit/extensions/test_extraroute.py +++ b/neutron/tests/unit/extensions/test_extraroute.py @@ -17,7 +17,6 @@ from neutron_lib.api.definitions import external_net as enet_apidef from neutron_lib.api.definitions import extraroute as xroute_apidef from neutron_lib.api.definitions import l3 as l3_apidef from neutron_lib import constants -from neutron_lib import context from neutron_lib.utils import helpers from oslo_config import cfg from oslo_utils import uuidutils @@ -62,14 +61,15 @@ class TestExtraRouteL3NatServicePlugin(test_l3.TestL3NatServicePlugin, class ExtraRouteDBTestCaseBase(object): def _routes_update_prepare( self, router_id, subnet_id, - port_id, routes, skip_add=False, tenant_id=None): + port_id, routes, skip_add=False, tenant_id=None, as_admin=False): if not skip_add: self._router_interface_action( - 'add', router_id, subnet_id, port_id, tenant_id=None) - ctxt = context.Context('', tenant_id) if tenant_id else None + 'add', router_id, subnet_id, port_id, tenant_id=tenant_id, + as_admin=as_admin) + tenant_id = tenant_id or self._tenant_id self._update('routers', router_id, {'router': {'routes': routes}}, - neutron_context=ctxt) - return self._show('routers', router_id) + request_tenant_id=tenant_id, as_admin=as_admin) + return self._show('routers', router_id, tenant_id=tenant_id) def _routes_update_cleanup(self, port_id, subnet_id, router_id, routes): self._update('routers', router_id, {'router': {'routes': routes}}) @@ -91,7 +91,8 @@ class ExtraRouteDBTestCaseBase(object): def test_route_update_with_external_route(self): my_tenant = 'tenant1' with self.subnet(cidr='10.0.1.0/24', tenant_id='notme') as ext_subnet,\ - self.port(subnet=ext_subnet) as nexthop_port: + self.port(subnet=ext_subnet, + tenant_id='notme') as nexthop_port: nexthop_ip = nexthop_port['port']['fixed_ips'][0]['ip_address'] routes = [{'destination': '135.207.0.0/16', 'nexthop': nexthop_ip}] @@ -107,14 +108,14 @@ class ExtraRouteDBTestCaseBase(object): def test_route_update_with_route_via_another_tenant_subnet(self): my_tenant = 'tenant1' with self.subnet(cidr='10.0.1.0/24', tenant_id='notme') as subnet,\ - self.port(subnet=subnet) as nexthop_port: + self.port(subnet=subnet, tenant_id='notme') as nexthop_port: nexthop_ip = nexthop_port['port']['fixed_ips'][0]['ip_address'] routes = [{'destination': '135.207.0.0/16', 'nexthop': nexthop_ip}] with self.router(tenant_id=my_tenant) as r: body = self._routes_update_prepare( r['router']['id'], subnet['subnet']['id'], None, routes, - tenant_id=my_tenant) + tenant_id=my_tenant, as_admin=True) self.assertEqual(routes, body['router']['routes']) def test_route_clear_routes_with_None(self): diff --git a/neutron/tests/unit/extensions/test_flavors.py b/neutron/tests/unit/extensions/test_flavors.py index cf8dadc707..5589a88356 100644 --- a/neutron/tests/unit/extensions/test_flavors.py +++ b/neutron/tests/unit/extensions/test_flavors.py @@ -198,7 +198,9 @@ class FlavorExtensionTestCase(extension.ExtensionTestCase): 'service_profiles': ['profile-1']}} instance = self.plugin.return_value instance.get_flavor.return_value = expected['flavor'] - res = self.api.get(_get_path('flavors', id=flavor_id, fmt=self.fmt)) + res = self.api.get( + _get_path('flavors', id=flavor_id, fmt=self.fmt), + extra_environ=test_base._get_neutron_env(as_admin=True)) instance.get_flavor.assert_called_with(mock.ANY, flavor_id, fields=mock.ANY) @@ -218,7 +220,9 @@ class FlavorExtensionTestCase(extension.ExtensionTestCase): 'service_profiles': ['profile-2', 'profile-1']}]} instance = self.plugin.return_value instance.get_flavors.return_value = data['flavors'] - res = self.api.get(_get_path('flavors', fmt=self.fmt)) + res = self.api.get( + _get_path('flavors', fmt=self.fmt), + extra_environ=test_base._get_neutron_env(as_admin=True)) instance.get_flavors.assert_called_with(mock.ANY, fields=mock.ANY, filters=mock.ANY) diff --git a/neutron/tests/unit/extensions/test_floating_ip_port_forwarding.py b/neutron/tests/unit/extensions/test_floating_ip_port_forwarding.py index b4658a180b..b90b0c73d7 100644 --- a/neutron/tests/unit/extensions/test_floating_ip_port_forwarding.py +++ b/neutron/tests/unit/extensions/test_floating_ip_port_forwarding.py @@ -14,7 +14,6 @@ from unittest import mock -from neutron_lib import context from oslo_utils import uuidutils from webob import exc @@ -50,8 +49,9 @@ class FloatingIPPorForwardingTestCase(test_l3.L3BaseForIntTests, tenant_id=None, description=None, external_port_range=None, - internal_port_range=None): - tenant_id = tenant_id or _uuid() + internal_port_range=None, + as_admin=False): + tenant_id = tenant_id or self._tenant_id data = {'port_forwarding': { "protocol": protocol, "internal_ip_address": internal_ip_address, @@ -69,28 +69,29 @@ class FloatingIPPorForwardingTestCase(test_l3.L3BaseForIntTests, if description: data['port_forwarding']['description'] = description - fip_pf_req = self._req( - 'POST', 'floatingips', data, - fmt or self.fmt, id=floating_ip_id, - subresource='port_forwardings') - - fip_pf_req.environ['neutron.context'] = context.Context( - '', tenant_id, is_admin=True) + fip_pf_req = self.new_create_request( + 'floatingips', data, fmt or self.fmt, floating_ip_id, + subresource='port_forwardings', + tenant_id=tenant_id, as_admin=as_admin) return fip_pf_req.get_response(self.ext_api) def _update_fip_port_forwarding(self, fmt, floating_ip_id, - port_forwarding_id, **kwargs): + port_forwarding_id, + req_tenant_id=None, as_admin=False, + **kwargs): + req_tenant_id = req_tenant_id or self._tenant_id port_forwarding = {} for k, v in kwargs.items(): port_forwarding[k] = v data = {'port_forwarding': port_forwarding} - fip_pf_req = self._req( - 'PUT', 'floatingips', data, - fmt or self.fmt, id=floating_ip_id, + fip_pf_req = self.new_update_request( + 'floatingips', data, floating_ip_id, fmt or self.fmt, sub_id=port_forwarding_id, - subresource='port_forwardings') + subresource='port_forwardings', + tenant_id=req_tenant_id, + as_admin=as_admin) return fip_pf_req.get_response(self.ext_api) diff --git a/neutron/tests/unit/extensions/test_l3.py b/neutron/tests/unit/extensions/test_l3.py index ab6be0ad52..f07472fcbc 100644 --- a/neutron/tests/unit/extensions/test_l3.py +++ b/neutron/tests/unit/extensions/test_l3.py @@ -377,10 +377,10 @@ class TestL3NatAgentSchedulingServicePlugin(TestL3NatServicePlugin, class L3NatTestCaseMixin(object): - def _create_router(self, fmt, tenant_id, name=None, - admin_state_up=None, set_context=False, - arg_list=None, **kwargs): - tenant_id = tenant_id or _uuid() + def _create_router(self, fmt, tenant_id=None, name=None, + admin_state_up=None, arg_list=None, + as_admin=False, **kwargs): + tenant_id = tenant_id or self._tenant_id data = {'router': {'tenant_id': tenant_id}} if name: data['router']['name'] = name @@ -400,29 +400,27 @@ class L3NatTestCaseMixin(object): if 'enable_ndp_proxy' in kwargs: data['router']['enable_ndp_proxy'] = \ bool(kwargs['enable_ndp_proxy']) - router_req = self.new_create_request('routers', data, fmt) - if set_context and tenant_id: - # create a specific auth context for this request - router_req.environ['neutron.context'] = context.Context( - '', tenant_id) + router_req = self.new_create_request('routers', data, fmt, + tenant_id=tenant_id, + as_admin=as_admin) return router_req.get_response(self.ext_api) - def _make_router(self, fmt, tenant_id, name=None, admin_state_up=None, - external_gateway_info=None, set_context=False, - arg_list=None, **kwargs): + def _make_router(self, fmt, tenant_id=None, name=None, admin_state_up=None, + external_gateway_info=None, + arg_list=None, as_admin=False, **kwargs): if external_gateway_info: arg_list = ('external_gateway_info', ) + (arg_list or ()) res = self._create_router(fmt, tenant_id, name, - admin_state_up, set_context, + admin_state_up, arg_list=arg_list, external_gateway_info=external_gateway_info, - **kwargs) + as_admin=as_admin, **kwargs) return self.deserialize(fmt, res) def _add_external_gateway_to_router(self, router_id, network_id, expected_code=exc.HTTPOk.code, - neutron_context=None, ext_ips=None, + ext_ips=None, as_admin=False, **kwargs): ext_ips = ext_ips or [] body = {'router': @@ -435,7 +433,7 @@ class L3NatTestCaseMixin(object): 'qos_policy_id'] = kwargs.get('policy_id') return self._update('routers', router_id, body, expected_code=expected_code, - neutron_context=neutron_context) + as_admin=as_admin) def _remove_external_gateway_from_router(self, router_id, network_id, expected_code=exc.HTTPOk.code, @@ -449,7 +447,8 @@ class L3NatTestCaseMixin(object): expected_code=exc.HTTPOk.code, expected_body=None, tenant_id=None, - msg=None): + msg=None, + as_admin=False): interface_data = {} if subnet_id is not None: interface_data.update({'subnet_id': subnet_id}) @@ -457,11 +456,8 @@ class L3NatTestCaseMixin(object): interface_data.update({'port_id': port_id}) req = self.new_action_request('routers', interface_data, router_id, - "%s_router_interface" % action) - # if tenant_id was specified, create a tenant context for this request - if tenant_id: - req.environ['neutron.context'] = context.Context( - '', tenant_id) + "%s_router_interface" % action, + tenant_id=tenant_id, as_admin=as_admin) res = req.get_response(self.ext_api) self.assertEqual(expected_code, res.status_int, msg) response = self.deserialize(self.fmt, res) @@ -472,23 +468,23 @@ class L3NatTestCaseMixin(object): @contextlib.contextmanager def router(self, name='router1', admin_state_up=True, fmt=None, project_id=None, - external_gateway_info=None, set_context=False, + external_gateway_info=None, as_admin=False, **kwargs): tenant_id = project_id if project_id else kwargs.pop( 'tenant_id', None) router = self._make_router(fmt or self.fmt, tenant_id, name, admin_state_up, external_gateway_info, - set_context, **kwargs) + as_admin=as_admin, **kwargs) yield router def _set_net_external(self, net_id): self._update('networks', net_id, - {'network': {extnet_apidef.EXTERNAL: True}}) + {'network': {extnet_apidef.EXTERNAL: True}}, + as_admin=True) def _create_floatingip(self, fmt, network_id, port_id=None, - fixed_ip=None, set_context=False, - floating_ip=None, subnet_id=None, - tenant_id=None, **kwargs): + fixed_ip=None, floating_ip=None, subnet_id=None, + tenant_id=None, as_admin=False, **kwargs): tenant_id = tenant_id or self._tenant_id data = {'floatingip': {'floating_network_id': network_id, 'tenant_id': tenant_id}} @@ -505,20 +501,18 @@ class L3NatTestCaseMixin(object): data['floatingip'].update(kwargs) - floatingip_req = self.new_create_request('floatingips', data, fmt) - if set_context and tenant_id: - # create a specific auth context for this request - floatingip_req.environ['neutron.context'] = context.Context( - '', tenant_id) + floatingip_req = self.new_create_request( + 'floatingips', data, fmt, tenant_id=tenant_id, as_admin=as_admin) return floatingip_req.get_response(self.ext_api) def _make_floatingip(self, fmt, network_id, port_id=None, - fixed_ip=None, set_context=False, tenant_id=None, + fixed_ip=None, tenant_id=None, floating_ip=None, http_status=exc.HTTPCreated.code, - **kwargs): + as_admin=False, **kwargs): res = self._create_floatingip(fmt, network_id, port_id, - fixed_ip, set_context, floating_ip, - tenant_id=tenant_id, **kwargs) + fixed_ip, floating_ip, + tenant_id=tenant_id, as_admin=as_admin, + **kwargs) self.assertEqual(http_status, res.status_int) return self.deserialize(fmt, res) @@ -534,16 +528,15 @@ class L3NatTestCaseMixin(object): @contextlib.contextmanager def floatingip_with_assoc(self, port_id=None, fmt=None, fixed_ip=None, - public_cidr='11.0.0.0/24', set_context=False, - project_id=None, flavor_id=None, **kwargs): + public_cidr='11.0.0.0/24', project_id=None, + flavor_id=None, as_admin=False, **kwargs): tenant_id = project_id if project_id else kwargs.pop( 'tenant_id', None) with self.subnet(cidr=public_cidr, - set_context=set_context, - tenant_id=tenant_id) as public_sub: + tenant_id=tenant_id, + as_admin=as_admin) as public_sub: self._set_net_external(public_sub['subnet']['network_id']) - args_list = {'set_context': set_context, - 'tenant_id': tenant_id} + args_list = {'tenant_id': tenant_id} if flavor_id: args_list['flavor_id'] = flavor_id private_port = None @@ -551,8 +544,8 @@ class L3NatTestCaseMixin(object): private_port = self._show('ports', port_id) with test_db_base_plugin_v2.optional_ctx( private_port, self.port, - set_context=set_context, - tenant_id=tenant_id) as private_port: + tenant_id=tenant_id, + is_admin=as_admin) as private_port: with self.router(**args_list) as r: sid = private_port['port']['fixed_ips'][0]['subnet_id'] private_sub = {'subnet': {'id': sid}} @@ -571,7 +564,7 @@ class L3NatTestCaseMixin(object): port_id=private_port['port']['id'], fixed_ip=fixed_ip, tenant_id=tenant_id, - set_context=set_context, + as_admin=as_admin, **kwargs) yield floatingip @@ -581,8 +574,8 @@ class L3NatTestCaseMixin(object): @contextlib.contextmanager def floatingip_no_assoc_with_public_sub(self, private_sub, fmt=None, - set_context=False, public_sub=None, - flavor_id=None, **kwargs): + public_sub=None, flavor_id=None, + as_admin=False, **kwargs): if 'project_id' in kwargs: kwargs['tenant_id'] = kwargs['project_id'] self._set_net_external(public_sub['subnet']['network_id']) @@ -606,7 +599,7 @@ class L3NatTestCaseMixin(object): floatingip = self._make_floatingip( fmt or self.fmt, public_sub['subnet']['network_id'], - set_context=set_context, + as_admin=as_admin, **kwargs) yield floatingip, r @@ -615,14 +608,14 @@ class L3NatTestCaseMixin(object): floatingip['floatingip']['id']) @contextlib.contextmanager - def floatingip_no_assoc(self, private_sub, fmt=None, - set_context=False, flavor_id=None, **kwargs): + def floatingip_no_assoc(self, private_sub, fmt=None, flavor_id=None, + as_admin=False, **kwargs): if 'project_id' in kwargs: kwargs['tenant_id'] = kwargs['project_id'] with self.subnet(cidr='12.0.0.0/24') as public_sub: with self.floatingip_no_assoc_with_public_sub( - private_sub, fmt, set_context, public_sub, - flavor_id, **kwargs) as (f, r): + private_sub, fmt, public_sub, flavor_id, + as_admin=as_admin, **kwargs) as (f, r): # Yield only the floating ip object yield f @@ -707,10 +700,10 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): def test_router_create_with_gwinfo(self): with self.subnet() as s: self._set_net_external(s['subnet']['network_id']) - data = {'router': {'tenant_id': _uuid()}} - data['router']['name'] = 'router1' - data['router']['external_gateway_info'] = { - 'network_id': s['subnet']['network_id']} + data = {'router': { + 'name': 'router1', + 'external_gateway_info': { + 'network_id': s['subnet']['network_id']}}} router_req = self.new_create_request('routers', data, self.fmt) res = router_req.get_response(self.ext_api) router = self.deserialize(self.fmt, res) @@ -726,8 +719,9 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): 'external_fixed_ips': [{'ip_address': '10.0.0.99'}] } res = self._create_router( - self.fmt, _uuid(), arg_list=('external_gateway_info',), - external_gateway_info=ext_info + self.fmt, arg_list=('external_gateway_info',), + external_gateway_info=ext_info, + as_admin=True ) router = self.deserialize(self.fmt, res) self.assertEqual( @@ -749,8 +743,10 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): {'subnet_id': s['subnet']['id']}] } res = self._create_router( - self.fmt, _uuid(), arg_list=('external_gateway_info',), - external_gateway_info=ext_info + self.fmt, + arg_list=('external_gateway_info',), + external_gateway_info=ext_info, + as_admin=True ) router = self.deserialize(self.fmt, res) ext_ips = router['router']['external_gateway_info'][ @@ -768,8 +764,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): 'external_fixed_ips': [{'ip_address': '10.0.0.99'}] } res = self._create_router( - self.fmt, _uuid(), arg_list=('external_gateway_info',), - set_context=True, external_gateway_info=ext_info + self.fmt, arg_list=('external_gateway_info',), + external_gateway_info=ext_info ) self.assertEqual(exc.HTTPForbidden.code, res.status_int) @@ -873,7 +869,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): r['router']['id'], s['subnet']['network_id'], ext_ips=[{'ip_address': s['subnet']['gateway_ip']}], - expected_code=exc.HTTPBadRequest.code) + expected_code=exc.HTTPBadRequest.code, + as_admin=True) def test_router_update_gateway_with_invalid_external_ip(self): with self.router() as r: @@ -883,7 +880,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): r['router']['id'], s['subnet']['network_id'], ext_ips=[{'ip_address': '99.99.99.99'}], - expected_code=exc.HTTPBadRequest.code) + expected_code=exc.HTTPBadRequest.code, + as_admin=True) def test_router_update_gateway_with_invalid_external_subnet(self): with self.subnet() as s1,\ @@ -895,7 +893,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): s1['subnet']['network_id'], # this subnet is not on the same network so this should fail ext_ips=[{'subnet_id': s2['subnet']['id']}], - expected_code=exc.HTTPBadRequest.code) + expected_code=exc.HTTPBadRequest.code, + as_admin=True) def test_router_update_gateway_with_different_external_subnet(self): with self.network() as n: @@ -906,11 +905,13 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): res1 = self._add_external_gateway_to_router( r['router']['id'], n['network']['id'], - ext_ips=[{'subnet_id': s1['subnet']['id']}]) + ext_ips=[{'subnet_id': s1['subnet']['id']}], + as_admin=True) res2 = self._add_external_gateway_to_router( r['router']['id'], n['network']['id'], - ext_ips=[{'subnet_id': s2['subnet']['id']}]) + ext_ips=[{'subnet_id': s2['subnet']['id']}], + as_admin=True) fip1 = res1['router']['external_gateway_info']['external_fixed_ips'][0] fip2 = res2['router']['external_gateway_info']['external_fixed_ips'][0] self.assertEqual(s1['subnet']['id'], fip1['subnet_id']) @@ -944,7 +945,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): res1 = self._add_external_gateway_to_router( r['router']['id'], n['network']['id'], - ext_ips=[{'subnet_id': s1['subnet']['id']}]) + ext_ips=[{'subnet_id': s1['subnet']['id']}], + as_admin=True) fip1 = (res1['router']['external_gateway_info'] ['external_fixed_ips'][0]) self.assertEqual(s1['subnet']['id'], fip1['subnet_id']) @@ -953,7 +955,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): n['network']['id'], ext_ips=[{'ip_address': fip1['ip_address'], 'subnet_id': s1['subnet']['id']}, - {'subnet_id': s2['subnet']['id']}]) + {'subnet_id': s2['subnet']['id']}], + as_admin=True) self.assertEqual(fip1, res2['router']['external_gateway_info'] ['external_fixed_ips'][0]) fip2 = (res2['router']['external_gateway_info'] @@ -971,7 +974,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): self._add_external_gateway_to_router( r['router']['id'], n['network']['id'], - ext_ips=[{'subnet_id': s1['subnet']['id']}]) + ext_ips=[{'subnet_id': s1['subnet']['id']}], + as_admin=True) plugin = directory.get_plugin(plugin_constants.L3) mock.patch.object( plugin, 'update_router', @@ -990,7 +994,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): res1 = self._add_external_gateway_to_router( r['router']['id'], n['network']['id'], - ext_ips=[{'subnet_id': s1['subnet']['id']}]) + ext_ips=[{'subnet_id': s1['subnet']['id']}], + as_admin=True) fip1 = (res1['router']['external_gateway_info'] ['external_fixed_ips'][0]) sres = self._create_subnet(self.fmt, net_id=n['network']['id'], @@ -1028,7 +1033,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): n['network']['id'], ext_ips=[{'subnet_id': s1['subnet']['id']}, {'subnet_id': s2['subnet']['id']}], - expected_code=exc.HTTPOk.code) + expected_code=exc.HTTPOk.code, + as_admin=True) res1 = self._show('routers', r['router']['id']) original_fips = (res1['router']['external_gateway_info'] ['external_fixed_ips']) @@ -1309,9 +1315,9 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): def test_router_add_interface_subnet_with_bad_tenant_returns_404(self): tenant_id = _uuid() - with self.router(tenant_id=tenant_id, set_context=True) as r: - with self.network(tenant_id=tenant_id, set_context=True) as n: - with self.subnet(network=n, set_context=True) as s: + with self.router(tenant_id=tenant_id) as r: + with self.network(tenant_id=tenant_id) as n: + with self.subnet(network=n, tenant_id=tenant_id) as s: err_code = exc.HTTPNotFound.code self._router_interface_action('add', r['router']['id'], @@ -1322,7 +1328,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): body = self._router_interface_action('add', r['router']['id'], s['subnet']['id'], - None) + None, + tenant_id=tenant_id) self.assertIn('port_id', body) self._router_interface_action('remove', r['router']['id'], @@ -1334,8 +1341,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): def test_router_add_interface_by_subnet_other_tenant_subnet_returns_400( self): router_tenant_id = _uuid() - with self.router(tenant_id=router_tenant_id, set_context=True) as r: - with self.network(shared=True) as n: + with self.router(tenant_id=router_tenant_id) as r: + with self.network(as_admin=True, shared=True) as n: with self.subnet(network=n) as s: err_code = exc.HTTPBadRequest.code self._router_interface_action('add', @@ -1350,10 +1357,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): ): router_tenant_id = _uuid() with mock.patch.object(network_obj.NetworkRBAC, "get_projects") as g: - with self.router( - tenant_id=router_tenant_id, set_context=True - ) as r: - with self.network(shared=True) as n: + with self.router(tenant_id=router_tenant_id) as r: + with self.network(as_admin=True, shared=True) as n: with self.subnet(network=n) as s: g.return_value = [router_tenant_id] self._router_interface_action( @@ -1369,8 +1374,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): self, out_of_pool=False, router_action_as_admin=False, expected_code=exc.HTTPOk.code): router_tenant_id = _uuid() - with self.router(tenant_id=router_tenant_id, set_context=True) as r: - with self.network(shared=True) as n: + with self.router(tenant_id=router_tenant_id) as r: + with self.network(as_admin=True, shared=True) as n: with self.subnet(network=n) as s1, ( self.subnet(network=n, cidr='fd00::/64', ip_version=lib_constants.IP_VERSION_6) @@ -1386,13 +1391,13 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): 'ip_address': s2['subnet']['gateway_ip']} with self.port(subnet=s1, fixed_ips=fixed_ips, - tenant_id=router_tenant_id) as p: - kwargs = {'expected_code': expected_code} - if not router_action_as_admin: - kwargs['tenant_id'] = router_tenant_id + tenant_id=router_tenant_id, + is_admin=True) as p: self._router_interface_action( 'add', r['router']['id'], None, p['port']['id'], - **kwargs) + expected_code=expected_code, + tenant_id=router_tenant_id, + as_admin=router_action_as_admin) def test_router_add_interface_by_port_other_tenant_address_in_pool( self): @@ -1414,13 +1419,17 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): with self.router(tenant_id=tenant_id) as r,\ self.network(tenant_id=tenant_id) as n1,\ self.network(tenant_id=other_tenant_id) as n2: - with self.subnet(network=n1, cidr='10.0.0.0/24') as s1,\ - self.subnet(network=n2, cidr='10.1.0.0/24') as s2: + with self.subnet(network=n1, cidr='10.0.0.0/24', + tenant_id=tenant_id) as s1,\ + self.subnet(network=n2, cidr='10.1.0.0/24', + tenant_id=other_tenant_id) as s2: body = self._router_interface_action( 'add', r['router']['id'], s2['subnet']['id'], - None) + None, + tenant_id=other_tenant_id, + as_admin=True) self.assertIn('port_id', body) self._router_interface_action( 'add', @@ -1472,7 +1481,7 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): {'ip_address': '1.1.1.1'}, {'ip_address': '2.2.2.2'}]}} self._update('ports', p['port']['id'], data, - neutron_context=context.get_admin_context(), + as_admin=True, expected_code=exc.HTTPBadRequest.code) self._router_interface_action('remove', @@ -1666,12 +1675,10 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): def test_router_add_interface_port_bad_tenant_returns_404(self): tenant_id = _uuid() - with self.router(tenant_id=tenant_id, set_context=True) as r: - with self.network(tenant_id=tenant_id, set_context=True) as n: - with self.subnet(tenant_id=tenant_id, network=n, - set_context=True) as s: - with self.port(tenant_id=tenant_id, subnet=s, - set_context=True) as p: + with self.router(tenant_id=tenant_id) as r: + with self.network(tenant_id=tenant_id) as n: + with self.subnet(tenant_id=tenant_id, network=n) as s: + with self.port(tenant_id=tenant_id, subnet=s) as p: err_code = exc.HTTPNotFound.code self._router_interface_action('add', r['router']['id'], @@ -1837,7 +1844,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): res = self._add_external_gateway_to_router( r['router']['id'], ext_net_id, ext_ips=[{'subnet_id': s1['subnet']['id']}], - expected_code=exc.HTTPBadRequest.code) + expected_code=exc.HTTPBadRequest.code, + as_admin=True) expected_msg = ( "Bad router request: Cidr 10.0.2.0/24 of subnet " "%(external_subnet_id)s overlaps with cidr 10.0.2.0/24 of " @@ -1967,15 +1975,12 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): self.assertIsNone(gw_info) def test_router_add_and_remove_gateway_tenant_ctx(self): - with self.router(tenant_id='noadmin', - set_context=True) as r: + with self.router() as r: with self.subnet() as s: self._set_net_external(s['subnet']['network_id']) - ctx = context.Context('', 'noadmin') self._add_external_gateway_to_router( r['router']['id'], - s['subnet']['network_id'], - neutron_context=ctx) + s['subnet']['network_id']) body = self._show('routers', r['router']['id']) net_id = body['router']['external_gateway_info']['network_id'] self.assertEqual(net_id, s['subnet']['network_id']) @@ -1988,8 +1993,7 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): def test_create_router_port_with_device_id_of_other_tenants_router(self): with self.router() as admin_router: - with self.network(tenant_id='tenant_a', - set_context=True) as n: + with self.network(tenant_id='tenant_a') as n: with self.subnet(network=n): for device_owner in lib_constants.ROUTER_INTERFACE_OWNERS: self._create_port( @@ -1997,7 +2001,6 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): tenant_id='tenant_a', device_id=admin_router['router']['id'], device_owner=device_owner, - set_context=True, expected_res_status=exc.HTTPConflict.code) def test_create_non_router_port_device_id_of_other_tenants_router_update( @@ -2006,38 +2009,32 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): # port that matches the device_id of another tenants router and then # we change the device_owner to be network:router_interface. with self.router() as admin_router: - with self.network(tenant_id='tenant_a', - set_context=True) as n: + with self.network(tenant_id='tenant_a') as n: with self.subnet(network=n): for device_owner in lib_constants.ROUTER_INTERFACE_OWNERS: port_res = self._create_port( self.fmt, n['network']['id'], tenant_id='tenant_a', - device_id=admin_router['router']['id'], - set_context=True) + device_id=admin_router['router']['id']) port = self.deserialize(self.fmt, port_res) - neutron_context = context.Context('', 'tenant_a') data = {'port': {'device_owner': device_owner}} self._update('ports', port['port']['id'], data, - neutron_context=neutron_context, - expected_code=exc.HTTPConflict.code) + expected_code=exc.HTTPConflict.code, + request_tenant_id='tenant_a') def test_update_port_device_id_to_different_tenants_router(self): with self.router() as admin_router: - with self.router(tenant_id='tenant_a', - set_context=True) as tenant_router: - with self.network(tenant_id='tenant_a', - set_context=True) as n: + with self.router(tenant_id='tenant_a') as tenant_router: + with self.network(tenant_id='tenant_a') as n: with self.subnet(network=n) as s: port = self._router_interface_action( 'add', tenant_router['router']['id'], s['subnet']['id'], None, tenant_id='tenant_a') - neutron_context = context.Context('', 'tenant_a') data = {'port': {'device_id': admin_router['router']['id']}} self._update('ports', port['port_id'], data, - neutron_context=neutron_context, - expected_code=exc.HTTPConflict.code) + expected_code=exc.HTTPConflict.code, + request_tenant_id='tenant_a') def test_router_add_gateway_invalid_network_returns_400(self): with self.router() as r: @@ -2122,7 +2119,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): res = self._add_external_gateway_to_router( r['router']['id'], n['network']['id'], ext_ips=[{'subnet_id': s['subnet']['id'], - 'ip_address': '10.0.0.4'}]) + 'ip_address': '10.0.0.4'}], + as_admin=True) gw_info = res['router']['external_gateway_info'] ext_ips = gw_info['external_fixed_ips'][0] expected_gw_ips = [ext_ips['ip_address']] @@ -2314,7 +2312,7 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): def test_router_delete_with_port_existed_returns_409(self): with self.subnet() as subnet: - res = self._create_router(self.fmt, _uuid()) + res = self._create_router(self.fmt) router = self.deserialize(self.fmt, res) self._router_interface_action('add', router['router']['id'], @@ -2329,7 +2327,7 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): p['port']['fixed_ips'][0]['subnet_id']}} with self.subnet(cidr='12.0.0.0/24') as public_sub: self._set_net_external(public_sub['subnet']['network_id']) - res = self._create_router(self.fmt, _uuid()) + res = self._create_router(self.fmt) r = self.deserialize(self.fmt, res) self._add_external_gateway_to_router( r['router']['id'], @@ -2346,12 +2344,10 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): def test_router_show(self): name = 'router1' - tenant_id = _uuid() - expected_value = [('name', name), ('tenant_id', tenant_id), + expected_value = [('name', name), ('tenant_id', self._tenant_id), ('admin_state_up', True), ('status', 'ACTIVE'), ('external_gateway_info', None)] - with self.router(name='router1', admin_state_up=True, - tenant_id=tenant_id) as router: + with self.router(name='router1', admin_state_up=True) as router: res = self._show('routers', router['router']['id']) for k, v in expected_value: self.assertEqual(res['router'][k], v) @@ -2365,7 +2361,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): s1['subnet']['network_id']) self._update('networks', s1['subnet']['network_id'], {'network': {extnet_apidef.EXTERNAL: False}}, - expected_code=exc.HTTPConflict.code) + expected_code=exc.HTTPConflict.code, + as_admin=True) def test_network_update_external(self): with self.router() as r: @@ -2377,7 +2374,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): r['router']['id'], s1['subnet']['network_id']) self._update('networks', testnet['network']['id'], - {'network': {extnet_apidef.EXTERNAL: False}}) + {'network': {extnet_apidef.EXTERNAL: False}}, + as_admin=True) def test_floatingip_crd_ops(self): with self.floatingip_with_assoc() as fip: @@ -2457,8 +2455,7 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): self._make_floatingip( self.fmt, public_sub['subnet']['network_id'], - port_id=private_port['port']['id'], - set_context=False) + port_id=private_port['port']['id']) self.assertTrue(agent_notification.called) def test_floating_port_status_not_applicable(self): @@ -2903,23 +2900,23 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): with self.subnet(cidr='11.0.0.0/24') as public_sub: self._set_net_external(public_sub['subnet']['network_id']) with self.port() as private_port: - with self.router(tenant_id='router-owner', - set_context=True) as r: + with self.router(tenant_id='router-owner') as r: sid = private_port['port']['fixed_ips'][0]['subnet_id'] private_sub = {'subnet': {'id': sid}} self._add_external_gateway_to_router( r['router']['id'], - public_sub['subnet']['network_id']) + public_sub['subnet']['network_id'], + as_admin=True) self._router_interface_action( 'add', r['router']['id'], - private_sub['subnet']['id'], None) + private_sub['subnet']['id'], None, + as_admin=True) self._make_floatingip(self.fmt, public_sub['subnet']['network_id'], port_id=private_port['port']['id'], - fixed_ip=None, - set_context=True) + fixed_ip=None) def test_floatingip_update_different_router(self): # Create subnet with different CIDRs to account for plugins which @@ -2983,10 +2980,12 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): def test_floatingip_update_different_port_owner_as_admin(self): with self.subnet() as private_sub: with self.floatingip_no_assoc(private_sub) as fip: - with self.port(subnet=private_sub, tenant_id='other') as p: + with self.port(subnet=private_sub, tenant_id='other', + is_admin=True) as p: body = self._update('floatingips', fip['floatingip']['id'], {'floatingip': - {'port_id': p['port']['id']}}) + {'port_id': p['port']['id']}}, + as_admin=True) self.assertEqual(p['port']['id'], body['floatingip']['port_id']) @@ -3032,7 +3031,7 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): p['port']['fixed_ips'][0]['subnet_id']}} with self.subnet(cidr='12.0.0.0/24') as public_sub: self._set_net_external(public_sub['subnet']['network_id']) - res = self._create_router(self.fmt, _uuid()) + res = self._create_router(self.fmt) r = self.deserialize(self.fmt, res) self._add_external_gateway_to_router( r['router']['id'], @@ -3060,8 +3059,7 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): res = self._create_floatingip( self.fmt, public_sub['subnet']['network_id'], - subnet_id=public_sub['subnet']['id'], - set_context=True) + subnet_id=public_sub['subnet']['id']) self.assertEqual(exc.HTTPCreated.code, res.status_int) def test_create_floatingip_with_subnet_id_and_fip_address(self): @@ -3073,7 +3071,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): self.fmt, ext_net['network']['id'], subnet_id=ext_subnet['subnet']['id'], - floating_ip='10.10.10.100') + floating_ip='10.10.10.100', + as_admin=True) fip = self.deserialize(self.fmt, res) self.assertEqual(exc.HTTPCreated.code, res.status_int) self.assertEqual('10.10.10.100', @@ -3088,7 +3087,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): self.fmt, ext_net['network']['id'], subnet_id=ext_subnet['subnet']['id'], - floating_ip='20.20.20.200') + floating_ip='20.20.20.200', + as_admin=True) data = self.deserialize(self.fmt, res) self.assertEqual(exc.HTTPBadRequest.code, res.status_int) msg = str(n_exc.InvalidIpForSubnet(ip_address='20.20.20.200')) @@ -3472,7 +3472,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): network_id = s['subnet']['network_id'] self._set_net_external(network_id) fp = self._make_floatingip(self.fmt, network_id, - floating_ip='10.0.0.10') + floating_ip='10.0.0.10', + as_admin=True) self.assertEqual('10.0.0.10', fp['floatingip']['floating_ip_address']) @@ -3484,18 +3485,17 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): network_id = s['subnet']['network_id'] self._set_net_external(network_id) fp = self._make_floatingip(self.fmt, network_id, - floating_ip='10.0.0.30') + floating_ip='10.0.0.30', + as_admin=True) self.assertEqual('10.0.0.30', fp['floatingip']['floating_ip_address']) def test_create_floatingip_with_specific_ip_non_admin(self): - ctx = context.Context('user_id', 'tenant_id') - with self.subnet(cidr='10.0.0.0/24') as s: network_id = s['subnet']['network_id'] self._set_net_external(network_id) self._make_floatingip(self.fmt, network_id, - set_context=ctx, + tenant_id='tenant_id', floating_ip='10.0.0.10', http_status=exc.HTTPForbidden.code) @@ -3506,7 +3506,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): self._set_net_external(network_id) self._make_floatingip(self.fmt, network_id, floating_ip='10.0.1.10', - http_status=exc.HTTPBadRequest.code) + http_status=exc.HTTPBadRequest.code, + as_admin=True) def test_create_floatingip_with_duplicated_specific_ip(self): @@ -3514,11 +3515,13 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): network_id = s['subnet']['network_id'] self._set_net_external(network_id) self._make_floatingip(self.fmt, network_id, - floating_ip='10.0.0.10') + floating_ip='10.0.0.10', + as_admin=True) self._make_floatingip(self.fmt, network_id, floating_ip='10.0.0.10', - http_status=exc.HTTPConflict.code) + http_status=exc.HTTPConflict.code, + as_admin=True) def test_create_floatingips_native_quotas(self): quota = 1 @@ -3711,7 +3714,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): {'port_id': port['port']['id']}) # fetch port and confirm device_id and device_owner - body = self._show('ports', port['port']['id']) + body = self._show('ports', port['port']['id'], + tenant_id=tenant_id) self.assertEqual('', body['port']['device_owner']) self.assertEqual('', body['port']['device_id']) @@ -3756,7 +3760,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): data = {'port': {'fixed_ips': [ {'ip_address': gw_ip}]}} req = self.new_update_request('ports', data, - gw_port_id) + gw_port_id, + as_admin=True) res = self.deserialize(self.fmt, req.get_response(self.api)) self.assertEqual(gw_ip_len, len(res['port']['fixed_ips'])) @@ -3833,9 +3838,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): 'network_id': network['network']['id'], 'subnetpool_id': subnetpool_id, 'prefixlen': 24, - 'ip_version': lib_constants.IP_VERSION_4, - 'tenant_id': tenant_id}} - req = self.new_create_request('subnets', data) + 'ip_version': lib_constants.IP_VERSION_4}} + req = self.new_create_request('subnets', data, tenant_id=tenant_id) subnet = self.deserialize(self.fmt, req.get_response(self.api)) admin_ctx = context.get_admin_context() @@ -3881,7 +3885,7 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): # simulate a failed update by just setting the device_id of # the fip port back to PENDING data = {'port': {'device_id': 'PENDING'}} - self._update('ports', fip_port['id'], data) + self._update('ports', fip_port['id'], data, as_admin=True) plugin._clean_garbage() # first call just marks as candidate, so it shouldn't be changed port = self._show('ports', fip_port['id']) @@ -3925,7 +3929,7 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): events.BEFORE_DELETE) with self.subnet(): - res = self._create_router(self.fmt, _uuid()) + res = self._create_router(self.fmt) router = self.deserialize(self.fmt, res) self._delete('routers', router['router']['id'], exc.HTTPForbidden.code) @@ -4151,8 +4155,7 @@ class L3AgentDbTestCaseBase(L3NatTestCaseMixin): f = self._make_floatingip(self.fmt, public_sub['subnet']['network_id'], port_id=None, - fixed_ip=None, - set_context=True) + fixed_ip=None) self._delete('floatingips', f['floatingip']['id']) fake_method.assert_called_once_with( resources.FLOATING_IP, events.AFTER_DELETE, mock.ANY, @@ -4194,7 +4197,7 @@ class L3AgentDbTestCaseBase(L3NatTestCaseMixin): # converted into its API equivalent of 404 e404 = mock.Mock(side_effect=l3_exc.RouterNotFound(router_id='1')) registry.subscribe(e404, resources.ROUTER, events.PRECOMMIT_CREATE) - res = self._create_router(self.fmt, 'tenid') + res = self._create_router(self.fmt) self.assertEqual(exc.HTTPNotFound.code, res.status_int) # make sure nothing committed body = self._list('routers') @@ -4521,7 +4524,7 @@ class L3NatDBFloatingIpTestCaseWithDNS(L3BaseForSepTests, L3NatTestCaseMixin): self.mock_admin_client.reset_mock() def _create_network(self, fmt, name, admin_state_up, - arg_list=None, set_context=False, tenant_id=None, + arg_list=None, tenant_id=None, as_admin=False, **kwargs): new_arg_list = ('dns_domain',) if arg_list is not None: @@ -4529,12 +4532,12 @@ class L3NatDBFloatingIpTestCaseWithDNS(L3BaseForSepTests, L3NatTestCaseMixin): return super(L3NatDBFloatingIpTestCaseWithDNS, self)._create_network(fmt, name, admin_state_up, arg_list=new_arg_list, - set_context=set_context, tenant_id=tenant_id, + as_admin=as_admin, **kwargs) def _create_port(self, fmt, name, admin_state_up, - arg_list=None, set_context=False, tenant_id=None, + arg_list=None, tenant_id=None, is_admin=False, **kwargs): new_arg_list = ('dns_name',) if arg_list is not None: @@ -4542,8 +4545,8 @@ class L3NatDBFloatingIpTestCaseWithDNS(L3BaseForSepTests, L3NatTestCaseMixin): return super(L3NatDBFloatingIpTestCaseWithDNS, self)._create_port(fmt, name, admin_state_up, arg_list=new_arg_list, - set_context=set_context, tenant_id=tenant_id, + is_admin=is_admin, **kwargs) def _create_net_sub_port(self, dns_domain='', dns_name=''): diff --git a/neutron/tests/unit/extensions/test_l3_conntrack_helper.py b/neutron/tests/unit/extensions/test_l3_conntrack_helper.py index 12c1c273ab..e49125bb0a 100644 --- a/neutron/tests/unit/extensions/test_l3_conntrack_helper.py +++ b/neutron/tests/unit/extensions/test_l3_conntrack_helper.py @@ -19,7 +19,6 @@ from webob import exc from neutron_lib.api.definitions import l3 as l3_apidef from neutron_lib.api.definitions import l3_conntrack_helper as l3_ct -from neutron_lib import context from oslo_utils import uuidutils from neutron.extensions import l3 @@ -67,19 +66,16 @@ class L3NConntrackHelperTestCase(test_l3.L3BaseForIntTests, def _create_router_conntrack_helper(self, fmt, router_id, protocol, port, helper): - tenant_id = self.tenant_id or _uuid() data = {'conntrack_helper': { "protocol": protocol, "port": port, "helper": helper} } - router_ct_req = self._req( - 'POST', 'routers', data, + router_ct_req = self.new_create_request( + 'routers', data, fmt or self.fmt, id=router_id, - subresource='conntrack_helpers') - - router_ct_req.environ['neutron.context'] = context.Context( - '', tenant_id, is_admin=True) + subresource='conntrack_helpers', + as_admin=True) return router_ct_req.get_response(self.ext_api) @@ -90,11 +86,10 @@ class L3NConntrackHelperTestCase(test_l3.L3BaseForIntTests, conntrack_helper[k] = v data = {'conntrack_helper': conntrack_helper} - router_ct_req = self._req( - 'PUT', 'routers', data, - fmt or self.fmt, id=router_id, - sub_id=conntrack_helper_id, - subresource='conntrack_helpers') + router_ct_req = self.new_update_request( + 'routers', data, router_id, + fmt or self.fmt, sub_id=conntrack_helper_id, + subresource='conntrack_helpers', as_admin=True) return router_ct_req.get_response(self.ext_api) def test_create_ct_with_duplicate_entry(self): diff --git a/neutron/tests/unit/extensions/test_l3_ext_gw_mode.py b/neutron/tests/unit/extensions/test_l3_ext_gw_mode.py index 9c941738ab..f8cc6a4bca 100644 --- a/neutron/tests/unit/extensions/test_l3_ext_gw_mode.py +++ b/neutron/tests/unit/extensions/test_l3_ext_gw_mode.py @@ -380,7 +380,7 @@ class ExtGwModeIntTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, def _set_router_external_gateway(self, router_id, network_id, snat_enabled=None, expected_code=exc.HTTPOk.code, - neutron_context=None): + tenant_id=None, as_admin=False): ext_gw_info = {'network_id': network_id} # Need to set enable_snat also if snat_enabled == False if snat_enabled is not None: @@ -389,7 +389,8 @@ class ExtGwModeIntTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, {'router': {'external_gateway_info': ext_gw_info}}, expected_code=expected_code, - neutron_context=neutron_context) + request_tenant_id=tenant_id, + as_admin=as_admin) def test_router_gateway_set_fail_after_port_create(self): with self.router() as r, self.subnet() as s: @@ -444,7 +445,8 @@ class ExtGwModeIntTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, ('external_gateway_info', None)] with self.router(name=name, admin_state_up=True, tenant_id=tenant_id) as router: - res = self._show('routers', router['router']['id']) + res = self._show('routers', router['router']['id'], + tenant_id=tenant_id) for k, v in expected_value: self.assertEqual(res['router'][k], v) @@ -468,8 +470,10 @@ class ExtGwModeIntTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'subnet_id': s['subnet']['id']}]})] with self.router(name=name, admin_state_up=True, tenant_id=tenant_id, - external_gateway_info=input_value) as router: - res = self._show('routers', router['router']['id']) + external_gateway_info=input_value, + as_admin=True) as router: + res = self._show('routers', router['router']['id'], + tenant_id=tenant_id) for k, v in expected_value: self.assertEqual(v, res['router'][k]) @@ -493,7 +497,8 @@ class ExtGwModeIntTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, self._set_router_external_gateway( r['router']['id'], ext_net_id, snat_enabled=snat_input_value, - expected_code=expected_http_code) + expected_code=expected_http_code, + as_admin=True) if expected_http_code != exc.HTTPOk.code: return body = self._show('routers', r['router']['id']) diff --git a/neutron/tests/unit/extensions/test_l3_ndp_proxy.py b/neutron/tests/unit/extensions/test_l3_ndp_proxy.py index d5ce2d728a..1836219cc7 100644 --- a/neutron/tests/unit/extensions/test_l3_ndp_proxy.py +++ b/neutron/tests/unit/extensions/test_l3_ndp_proxy.py @@ -22,7 +22,6 @@ from neutron_lib.api.definitions import external_net as enet_apidef from neutron_lib.api.definitions import l3 as l3_apidef from neutron_lib.api.definitions import l3_ext_gw_mode from neutron_lib import constants -from neutron_lib import context from neutron_lib import fixture from oslo_config import cfg from oslo_utils import uuidutils @@ -66,7 +65,7 @@ class L3NDPProxyTestCase(test_address_scope.AddressScopeTestCase, test_l3.L3BaseForIntTests, test_l3.L3NatTestCaseMixin): fmt = 'json' - tenant_id = _uuid() + _tenant_id = _uuid() def setUp(self): mock.patch('neutron.api.rpc.handlers.resources_rpc.' @@ -81,11 +80,11 @@ class L3NDPProxyTestCase(test_address_scope.AddressScopeTestCase, self.address_scope_id = self._make_address_scope( self.fmt, constants.IP_VERSION_6, - **{'tenant_id': self.tenant_id})['address_scope']['id'] + **{'tenant_id': self._tenant_id})['address_scope']['id'] self.subnetpool_id = self._make_subnetpool( self.fmt, ['2001::0/96'], **{'address_scope_id': self.address_scope_id, - 'default_prefixlen': 112, 'tenant_id': self.tenant_id, + 'default_prefixlen': 112, 'name': "test-ipv6-pool"})['subnetpool']['id'] self.ext_net = self._make_network( self.fmt, 'ext-net', True) @@ -103,7 +102,7 @@ class L3NDPProxyTestCase(test_address_scope.AddressScopeTestCase, ipv6_ra_mode=constants.DHCPV6_STATEFUL, ipv6_address_mode=constants.DHCPV6_STATEFUL) self._ext_subnet_v6_id = self._ext_subnet_v6['subnet']['id'] - self.router1 = self._make_router(self.fmt, self.tenant_id) + self.router1 = self._make_router(self.fmt, self._tenant_id) self.router1_id = self.router1['router']['id'] self.private_net = self._make_network(self.fmt, 'private-net', True) self.private_subnet = self._make_subnet( @@ -125,7 +124,7 @@ class L3NDPProxyTestCase(test_address_scope.AddressScopeTestCase, description=None, fmt=None, tenant_id=None, expected_code=exc.HTTPCreated.code, expected_message=None): - tenant_id = tenant_id or self.tenant_id + tenant_id = tenant_id or self._tenant_id data = {'ndp_proxy': { "port_id": port_id, "router_id": router_id} @@ -135,11 +134,9 @@ class L3NDPProxyTestCase(test_address_scope.AddressScopeTestCase, if description: data['ndp_proxy']['description'] = description - req_res = self._req( - 'POST', 'ndp-proxies', data, - fmt or self.fmt) - req_res.environ['neutron.context'] = context.Context( - '', tenant_id, is_admin=True) + req_res = self.new_create_request( + 'ndp-proxies', data, fmt or self.fmt, + tenant_id=tenant_id, as_admin=True) res = req_res.get_response(self.ext_api) self.assertEqual(expected_code, res.status_int) @@ -152,15 +149,14 @@ class L3NDPProxyTestCase(test_address_scope.AddressScopeTestCase, tenant_id=None, fmt=None, expected_code=exc.HTTPOk.code, expected_message=None, **kwargs): - tenant_id = tenant_id or self.tenant_id + tenant_id = tenant_id or self._tenant_id data = {} for k, v in kwargs.items(): data[k] = v - req_res = self._req( - 'PUT', 'ndp-proxies', {'ndp_proxy': data}, - fmt or self.fmt, id=ndp_proxy_id) - req_res.environ['neutron.context'] = context.Context( - '', tenant_id, is_admin=True) + req_res = self.new_update_request( + 'ndp-proxies', {'ndp_proxy': data}, + ndp_proxy_id, fmt or self.fmt, + tenant_id=tenant_id, as_admin=True) res = req_res.get_response(self.ext_api) self.assertEqual(expected_code, res.status_int) if expected_message: @@ -208,13 +204,12 @@ class L3NDPProxyTestCase(test_address_scope.AddressScopeTestCase, def _update_router(self, router_id, update_date, tenant_id=None, fmt=None, expected_code=exc.HTTPOk.code, expected_message=None): - tenant_id = tenant_id or self.tenant_id + tenant_id = tenant_id or self._tenant_id data = {'router': update_date} router_req = self.new_update_request( 'routers', id=router_id, data=data, - fmt=(fmt or self.fmt)) - router_req.environ['neutron.context'] = context.Context( - '', tenant_id, is_admin=True) + fmt=(fmt or self.fmt), + tenant_id=tenant_id, as_admin=True) res = router_req.get_response(self.ext_api) self.assertEqual(expected_code, res.status_int) if expected_message: @@ -275,7 +270,7 @@ class L3NDPProxyTestCase(test_address_scope.AddressScopeTestCase, ipv6_address_mode=constants.DHCPV6_STATEFUL): self._set_net_external(ext_net['network']['id']) res = self._make_router( - self.fmt, self.tenant_id, + self.fmt, self._tenant_id, external_gateway_info={'network_id': ext_net['network']['id']}, **{'enable_ndp_proxy': True}) expected_msg = ( @@ -284,7 +279,7 @@ class L3NDPProxyTestCase(test_address_scope.AddressScopeTestCase, "scope.") % ext_net['network']['id'] self.assertTrue(expected_msg in res['NeutronError']['message']) router = self._make_router( - self.fmt, self.tenant_id, + self.fmt, self._tenant_id, external_gateway_info={'network_id': ext_net['network']['id']}) expected_msg = ( "Can not enable ndp proxy on router %s, The router has no " @@ -473,18 +468,18 @@ class L3NDPProxyTestCase(test_address_scope.AddressScopeTestCase, def test_create_ndp_proxy_with_different_address_scope(self): with self.address_scope( ip_version=constants.IP_VERSION_6, - tenant_id=self.tenant_id) as addr_scope, \ + tenant_id=self._tenant_id) as addr_scope, \ self.subnetpool(['2001::100:0:0/100'], **{'address_scope_id': addr_scope['address_scope']['id'], 'default_prefixlen': 112, 'name': 'test1', - 'tenant_id': self.tenant_id}) as subnetpool, \ + 'tenant_id': self._tenant_id}) as subnetpool, \ self.subnet( cidr='2001::100:1:0/112', ip_version=constants.IP_VERSION_6, ipv6_ra_mode=constants.DHCPV6_STATEFUL, ipv6_address_mode=constants.DHCPV6_STATEFUL, subnetpool_id=subnetpool['subnetpool']['id'], - tenant_id=self.tenant_id) as subnet, \ + tenant_id=self._tenant_id) as subnet, \ self.port(subnet) as port: subnet_id = subnet['subnet']['id'] port_id = port['port']['id'] @@ -503,9 +498,7 @@ class L3NDPProxyTestCase(test_address_scope.AddressScopeTestCase, def _create_router(self, data, expected_code=exc.HTTPCreated.code, expected_message=None): router_req = self.new_create_request( - 'routers', data, self.fmt) - router_req.environ['neutron.context'] = context.Context( - '', self.tenant_id, is_admin=True) + 'routers', data, self.fmt, as_admin=True) res = router_req.get_response(self.ext_api) self.assertEqual(expected_code, res.status_int) if expected_message: diff --git a/neutron/tests/unit/extensions/test_local_ip.py b/neutron/tests/unit/extensions/test_local_ip.py index 5de762d8b1..e15b31e821 100644 --- a/neutron/tests/unit/extensions/test_local_ip.py +++ b/neutron/tests/unit/extensions/test_local_ip.py @@ -19,7 +19,6 @@ from unittest import mock import netaddr from neutron_lib.api.definitions import local_ip as apidef from neutron_lib import constants -from neutron_lib import context import webob.exc from neutron.extensions import local_ip as lip_ext @@ -46,10 +45,8 @@ class LocalIPTestBase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): for k, v in kwargs.items(): local_ip['local_ip'][k] = v - req = self.new_create_request('local-ips', local_ip) - neutron_context = context.Context( - '', kwargs.get('project_id', self._tenant_id), is_admin=True) - req.environ['neutron.context'] = neutron_context + req = self.new_create_request('local-ips', local_ip, + tenant_id=self._tenant_id, as_admin=True) res = req.get_response(self.ext_api) if res.status_int >= webob.exc.HTTPClientError.code: raise webob.exc.HTTPClientError(code=res.status_int) @@ -57,9 +54,7 @@ class LocalIPTestBase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): def _update_local_ip(self, lip_id, data): update_req = self.new_update_request( - 'local-ips', data, lip_id) - update_req.environ['neutron.context'] = context.Context( - '', self._tenant_id) + 'local-ips', data, lip_id, tenant_id=self._tenant_id) res = update_req.get_response(self.ext_api) if res.status_int >= webob.exc.HTTPClientError.code: raise webob.exc.HTTPClientError(code=res.status_int) @@ -73,9 +68,8 @@ class LocalIPTestBase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): req = self.new_create_request('local_ips', data=local_ip_assoc, id=local_ip_id, - subresource='port_associations') - neutron_context = context.Context('', self._tenant_id) - req.environ['neutron.context'] = neutron_context + subresource='port_associations', + tenant_id=self._tenant_id) res = req.get_response(self.ext_api) if res.status_int >= webob.exc.HTTPClientError.code: raise webob.exc.HTTPClientError(code=res.status_int) diff --git a/neutron/tests/unit/extensions/test_network_ip_availability.py b/neutron/tests/unit/extensions/test_network_ip_availability.py index 833ee89c95..f52d000d9a 100644 --- a/neutron/tests/unit/extensions/test_network_ip_availability.py +++ b/neutron/tests/unit/extensions/test_network_ip_availability.py @@ -65,7 +65,9 @@ class TestNetworkIPAvailabilityAPI( with self.subnet(network=net): # list by query fields: total_ips params = 'fields=total_ips' - request = self.new_list_request(API_RESOURCE, params=params) + request = self.new_list_request(API_RESOURCE, + params=params, + as_admin=True) response = self.deserialize(self.fmt, request.get_response(self.ext_api)) self.assertIn(IP_AVAILS_KEY, response) @@ -83,7 +85,8 @@ class TestNetworkIPAvailabilityAPI( params = ['total_ips'] request = self.new_show_request(API_RESOURCE, network['id'], - fields=params) + fields=params, + as_admin=True) response = self.deserialize( self.fmt, request.get_response(self.ext_api)) self.assertIn(IP_AVAIL_KEY, response) @@ -103,7 +106,9 @@ class TestNetworkIPAvailabilityAPI( with self.subnet(network=net): network = net['network'] # Get ALL - request = self.new_list_request(API_RESOURCE, self.fmt) + request = self.new_list_request(API_RESOURCE, + self.fmt, + as_admin=True) response = self.deserialize(self.fmt, request.get_response(self.ext_api)) self.assertIn(IP_AVAILS_KEY, response) @@ -112,7 +117,8 @@ class TestNetworkIPAvailabilityAPI( net, 0) # Get single via id - request = self.new_show_request(API_RESOURCE, network['id']) + request = self.new_show_request(API_RESOURCE, network['id'], + as_admin=True) response = self.deserialize( self.fmt, request.get_response(self.ext_api)) self.assertIn(IP_AVAIL_KEY, response) @@ -134,7 +140,8 @@ class TestNetworkIPAvailabilityAPI( self.port(subnet=subnet3_1): # Test get ALL - request = self.new_list_request(API_RESOURCE) + request = self.new_list_request(API_RESOURCE, + as_admin=True) response = self.deserialize( self.fmt, request.get_response(self.ext_api)) self.assertIn(IP_AVAILS_KEY, response) @@ -148,7 +155,8 @@ class TestNetworkIPAvailabilityAPI( # Test get single via network id network = n1['network'] request = self.new_show_request(API_RESOURCE, - network['id']) + network['id'], + as_admin=True) response = self.deserialize( self.fmt, request.get_response(self.ext_api)) self.assertIn(IP_AVAIL_KEY, response) @@ -165,7 +173,8 @@ class TestNetworkIPAvailabilityAPI( self.port(subnet=subnet1_2),\ self.port(subnet=subnet1_2): # Get ALL - request = self.new_list_request(API_RESOURCE) + request = self.new_list_request(API_RESOURCE, + as_admin=True) response = self.deserialize( self.fmt, request.get_response(self.ext_api)) self.assertIn(IP_AVAILS_KEY, response) @@ -176,7 +185,8 @@ class TestNetworkIPAvailabilityAPI( # Get single via network id network = n1['network'] request = self.new_show_request(API_RESOURCE, - network['id']) + network['id'], + as_admin=True) response = self.deserialize( self.fmt, request.get_response(self.ext_api)) self.assertIn(IP_AVAIL_KEY, response) @@ -186,7 +196,8 @@ class TestNetworkIPAvailabilityAPI( def test_usages_port_consumed_v4(self): with self.network() as net: with self.subnet(network=net) as subnet: - request = self.new_list_request(API_RESOURCE) + request = self.new_list_request(API_RESOURCE, + as_admin=True) # Consume 2 ports with self.port(subnet=subnet), self.port(subnet=subnet): response = self.deserialize(self.fmt, @@ -200,7 +211,8 @@ class TestNetworkIPAvailabilityAPI( with self.subnet(network=net): # Get IPv4 params = 'ip_version=%s' % constants.IP_VERSION_4 - request = self.new_list_request(API_RESOURCE, params=params) + request = self.new_list_request(API_RESOURCE, params=params, + as_admin=True) response = self.deserialize(self.fmt, request.get_response(self.ext_api)) self.assertIn(IP_AVAILS_KEY, response) @@ -210,7 +222,8 @@ class TestNetworkIPAvailabilityAPI( # Get IPv6 should return empty array params = 'ip_version=%s' % constants.IP_VERSION_6 - request = self.new_list_request(API_RESOURCE, params=params) + request = self.new_list_request(API_RESOURCE, params=params, + as_admin=True) response = self.deserialize(self.fmt, request.get_response(self.ext_api)) self.assertEqual(0, len(response[IP_AVAILS_KEY])) @@ -225,7 +238,8 @@ class TestNetworkIPAvailabilityAPI( ipv6_address_mode=constants.DHCPV6_STATELESS): # Get IPv6 params = 'ip_version=%s' % constants.IP_VERSION_6 - request = self.new_list_request(API_RESOURCE, params=params) + request = self.new_list_request(API_RESOURCE, params=params, + as_admin=True) response = self.deserialize(self.fmt, request.get_response(self.ext_api)) self.assertEqual(1, len(response[IP_AVAILS_KEY])) @@ -234,7 +248,8 @@ class TestNetworkIPAvailabilityAPI( # Get IPv4 should return empty array params = 'ip_version=%s' % constants.IP_VERSION_4 - request = self.new_list_request(API_RESOURCE, params=params) + request = self.new_list_request(API_RESOURCE, params=params, + as_admin=True) response = self.deserialize(self.fmt, request.get_response(self.ext_api)) self.assertEqual(0, len(response[IP_AVAILS_KEY])) @@ -247,7 +262,8 @@ class TestNetworkIPAvailabilityAPI( network=net, cidr=cidr_ipv6, ip_version=constants.IP_VERSION_6, ipv6_address_mode=constants.DHCPV6_STATELESS) as subnet: - request = self.new_list_request(API_RESOURCE) + request = self.new_list_request(API_RESOURCE, + as_admin=True) # Consume 3 ports with self.port(subnet=subnet),\ self.port(subnet=subnet), \ @@ -266,7 +282,8 @@ class TestNetworkIPAvailabilityAPI( test_id = network['id'] # Get by query param: network_id params = 'network_id=%s' % test_id - request = self.new_list_request(API_RESOURCE, params=params) + request = self.new_list_request(API_RESOURCE, params=params, + as_admin=True) response = self.deserialize(self.fmt, request.get_response(self.ext_api)) self.assertIn(IP_AVAILS_KEY, response) @@ -276,7 +293,8 @@ class TestNetworkIPAvailabilityAPI( # Get by NON-matching query param: network_id params = 'network_id=clearlywontmatch' - request = self.new_list_request(API_RESOURCE, params=params) + request = self.new_list_request(API_RESOURCE, params=params, + as_admin=True) response = self.deserialize(self.fmt, request.get_response(self.ext_api)) self.assertEqual(0, len(response[IP_AVAILS_KEY])) @@ -287,7 +305,8 @@ class TestNetworkIPAvailabilityAPI( with self.subnet(network=net): # Get by query param: network_name params = 'network_name=%s' % test_name - request = self.new_list_request(API_RESOURCE, params=params) + request = self.new_list_request(API_RESOURCE, params=params, + as_admin=True) response = self.deserialize(self.fmt, request.get_response(self.ext_api)) self.assertIn(IP_AVAILS_KEY, response) @@ -297,7 +316,8 @@ class TestNetworkIPAvailabilityAPI( # Get by NON-matching query param: network_name params = 'network_name=clearly-wont-match' - request = self.new_list_request(API_RESOURCE, params=params) + request = self.new_list_request(API_RESOURCE, params=params, + as_admin=True) response = self.deserialize(self.fmt, request.get_response(self.ext_api)) self.assertEqual(0, len(response[IP_AVAILS_KEY])) @@ -308,7 +328,8 @@ class TestNetworkIPAvailabilityAPI( with self.subnet(network=net): # Get by query param: tenant_id params = 'tenant_id=%s' % test_tenant_id - request = self.new_list_request(API_RESOURCE, params=params) + request = self.new_list_request(API_RESOURCE, params=params, + as_admin=True) response = self.deserialize(self.fmt, request.get_response(self.ext_api)) self.assertIn(IP_AVAILS_KEY, response) @@ -320,7 +341,8 @@ class TestNetworkIPAvailabilityAPI( # Get by NON-matching query param: tenant_id params = 'tenant_id=clearly-wont-match' - request = self.new_list_request(API_RESOURCE, params=params) + request = self.new_list_request(API_RESOURCE, params=params, + as_admin=True) response = self.deserialize(self.fmt, request.get_response(self.ext_api)) self.assertEqual(0, len(response[IP_AVAILS_KEY])) @@ -331,7 +353,8 @@ class TestNetworkIPAvailabilityAPI( with self.subnet(network=net): # Get by query param: project_id params = 'project_id=%s' % test_project_id - request = self.new_list_request(API_RESOURCE, params=params) + request = self.new_list_request(API_RESOURCE, params=params, + as_admin=True) response = self.deserialize(self.fmt, request.get_response(self.ext_api)) self.assertIn(IP_AVAILS_KEY, response) @@ -343,7 +366,8 @@ class TestNetworkIPAvailabilityAPI( # Get by NON-matching query param: project_id params = 'project_id=clearly-wont-match' - request = self.new_list_request(API_RESOURCE, params=params) + request = self.new_list_request(API_RESOURCE, params=params, + as_admin=True) response = self.deserialize(self.fmt, request.get_response(self.ext_api)) self.assertEqual(0, len(response[IP_AVAILS_KEY])) @@ -369,7 +393,8 @@ class TestNetworkIPAvailabilityAPI( self.port(subnet=s42), self.port(subnet=s42): # Verify consumption across all - request = self.new_list_request(API_RESOURCE) + request = self.new_list_request(API_RESOURCE, + as_admin=True) response = self.deserialize( self.fmt, request.get_response(self.ext_api)) avails_list = response[IP_AVAILS_KEY] @@ -387,7 +412,8 @@ class TestNetworkIPAvailabilityAPI( constants.IP_VERSION_6]: params = 'ip_version=%i' % ip_ver request = self.new_list_request(API_RESOURCE, - params=params) + params=params, + as_admin=True) response = self.deserialize( self.fmt, request.get_response(self.ext_api)) for net_avail in response[IP_AVAILS_KEY]: @@ -399,7 +425,8 @@ class TestNetworkIPAvailabilityAPI( API_RESOURCE, params='network_id=%s&network_id=%s' % (net_v4_2['network']['id'], - net_v6_2['network']['id'])) + net_v6_2['network']['id']), + as_admin=True) response = self.deserialize( self.fmt, request.get_response(self.ext_api)) avails_list = response[IP_AVAILS_KEY] @@ -414,7 +441,8 @@ class TestNetworkIPAvailabilityAPI( networks = (net1, net2, net3, net4) for idx in range(1, len(networks) + 1): params = 'limit=%s' % idx - request = self.new_list_request(API_RESOURCE, params=params) + request = self.new_list_request(API_RESOURCE, params=params, + as_admin=True) response = self.deserialize(self.fmt, request.get_response(self.ext_api)) self.assertEqual(idx, len(response[IP_AVAILS_KEY])) @@ -426,14 +454,16 @@ class TestNetworkIPAvailabilityAPI( network_ids = sorted([net['network']['id'] for net in networks]) params = 'sort_key=network_id;sort_dir=asc' - request = self.new_list_request(API_RESOURCE, params=params) + request = self.new_list_request(API_RESOURCE, params=params, + as_admin=True) response = self.deserialize(self.fmt, request.get_response(self.ext_api)) res = [net['network_id'] for net in response[IP_AVAILS_KEY]] self.assertEqual(network_ids, res) params = 'sort_key=network_id;sort_dir=desc' - request = self.new_list_request(API_RESOURCE, params=params) + request = self.new_list_request(API_RESOURCE, params=params, + as_admin=True) response = self.deserialize(self.fmt, request.get_response(self.ext_api)) res = [net['network_id'] for net in response[IP_AVAILS_KEY]] diff --git a/neutron/tests/unit/extensions/test_network_segment_range.py b/neutron/tests/unit/extensions/test_network_segment_range.py index af43081e6f..9bf4ca3660 100644 --- a/neutron/tests/unit/extensions/test_network_segment_range.py +++ b/neutron/tests/unit/extensions/test_network_segment_range.py @@ -19,6 +19,7 @@ from neutron_lib import context from oslo_config import cfg import webob.exc +from neutron.common import config from neutron.db import db_base_plugin_v2 from neutron.db import segments_db from neutron.extensions import network_segment_range as ext_range @@ -55,7 +56,8 @@ class NetworkSegmentRangeTestBase(test_db_base_plugin_v2. network_segment_range['network_segment_range'][k] = str(v) network_segment_range_req = self.new_create_request( - 'network-segment-ranges', network_segment_range, fmt) + 'network-segment-ranges', network_segment_range, fmt, + as_admin=True) network_segment_range_res = network_segment_range_req.get_response( self.ext_api) @@ -83,7 +85,7 @@ class NetworkSegmentRangeTestBase(test_db_base_plugin_v2. def _test_update_network_segment_range(self, range_id, data, expected=None): update_req = self.new_update_request( - 'network-segment-ranges', data, range_id) + 'network-segment-ranges', data, range_id, as_admin=True) update_res = update_req.get_response(self.ext_api) if expected: @@ -112,6 +114,7 @@ class NetworkSegmentRangeTestPlugin(db_base_plugin_v2.NeutronDbPluginV2, class TestNetworkSegmentRange(NetworkSegmentRangeTestBase): def setUp(self, plugin=None): + config.register_common_config_options() if not plugin: plugin = TEST_PLUGIN_KLASS service_plugins = {'network_segment_range_plugin_name': @@ -262,7 +265,8 @@ class TestNetworkSegmentRange(NetworkSegmentRangeTestBase): 'network-segment-ranges', network_segment_range['network_segment_range']['id'], {'network_segment_range': {'name': 'foo-name'}}, - expected_code=webob.exc.HTTPOk.code) + expected_code=webob.exc.HTTPOk.code, + as_admin=True) self.assertEqual('foo-name', result['network_segment_range']['name']) @@ -275,7 +279,8 @@ class TestNetworkSegmentRange(NetworkSegmentRangeTestBase): 'network-segment-ranges', network_segment_range['network_segment_range']['id'], {'network_segment_range': {'name': ''}}, - expected_code=webob.exc.HTTPOk.code) + expected_code=webob.exc.HTTPOk.code, + as_admin=True) self.assertEqual('', result['network_segment_range']['name']) def test_update_network_segment_range_min_max(self): @@ -286,7 +291,8 @@ class TestNetworkSegmentRange(NetworkSegmentRangeTestBase): 'network-segment-ranges', network_segment_range['network_segment_range']['id'], {'network_segment_range': {'minimum': 1200, 'maximum': 1300}}, - expected_code=webob.exc.HTTPOk.code) + expected_code=webob.exc.HTTPOk.code, + as_admin=True) self.assertEqual(1200, result['network_segment_range']['minimum']) self.assertEqual(1300, result['network_segment_range']['maximum']) @@ -294,7 +300,8 @@ class TestNetworkSegmentRange(NetworkSegmentRangeTestBase): network_segment_range = self._test_create_network_segment_range() req = self.new_show_request( 'network-segment-ranges', - network_segment_range['network_segment_range']['id']) + network_segment_range['network_segment_range']['id'], + as_admin=True) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) self.assertEqual( network_segment_range['network_segment_range']['id'], @@ -304,7 +311,7 @@ class TestNetworkSegmentRange(NetworkSegmentRangeTestBase): self._test_create_network_segment_range(name='foo-range1') self._test_create_network_segment_range( name='foo-range2', minimum=400, maximum=500) - res = self._list('network-segment-ranges') + res = self._list('network-segment-ranges', as_admin=True) self.assertEqual(2, len(res['network_segment_ranges'])) def test_list_network_segment_ranges_with_sort(self): @@ -314,7 +321,8 @@ class TestNetworkSegmentRange(NetworkSegmentRangeTestBase): name='foo-range2', physical_network='phys_net2') self._test_list_with_sort('network-segment-range', (range2, range1), - [('name', 'desc')]) + [('name', 'desc')], + as_admin=True) def test_list_network_segment_ranges_with_pagination(self): range1 = self._test_create_network_segment_range( @@ -326,7 +334,8 @@ class TestNetworkSegmentRange(NetworkSegmentRangeTestBase): self._test_list_with_pagination( 'network-segment-range', (range1, range2, range3), - ('name', 'asc'), 2, 2) + ('name', 'asc'), 2, 2, + as_admin=True) def test_list_network_segment_ranges_with_pagination_reverse(self): range1 = self._test_create_network_segment_range( @@ -338,14 +347,17 @@ class TestNetworkSegmentRange(NetworkSegmentRangeTestBase): self._test_list_with_pagination_reverse( 'network-segment-range', (range1, range2, range3), - ('name', 'asc'), 2, 2) + ('name', 'asc'), 2, 2, + as_admin=True) def test_delete_network_segment_range(self): network_segment_range = self._test_create_network_segment_range() with mock.patch.object(segments_db, 'network_segments_exist_in_range', return_value=False): self._delete('network-segment-ranges', - network_segment_range['network_segment_range']['id']) + network_segment_range['network_segment_range']['id'], + as_admin=True) self._show('network-segment-ranges', network_segment_range['network_segment_range']['id'], - expected_code=webob.exc.HTTPNotFound.code) + expected_code=webob.exc.HTTPNotFound.code, + as_admin=True) diff --git a/neutron/tests/unit/extensions/test_port_hints.py b/neutron/tests/unit/extensions/test_port_hints.py new file mode 100644 index 0000000000..9aa9fb1462 --- /dev/null +++ b/neutron/tests/unit/extensions/test_port_hints.py @@ -0,0 +1,85 @@ +# Copyright 2023 Ericsson Software Technology +# +# 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 ddt +from neutron_lib.api.definitions import port_hints as phints_def +from neutron_lib.db import api as db_api + +from neutron.db import db_base_plugin_v2 +from neutron.db import port_hints_db as phints_db +from neutron.tests.unit.db import test_db_base_plugin_v2 + +HINTS_LIST = [ + None, + {'openvswitch': {'other_config': {'tx-steering': 'hash'}}}, +] + + +class PortHintsExtensionTestPlugin( + db_base_plugin_v2.NeutronDbPluginV2, + phints_db.PortHintsMixin): + """Test plugin to mixin the port hints extension.""" + + supported_extension_aliases = [phints_def.ALIAS] + + def create_port(self, context, port): + with db_api.CONTEXT_WRITER.using(context): + new_port = super(PortHintsExtensionTestPlugin, + self).create_port(context, port) + self._process_create_port(context, port['port'], new_port) + return new_port + + def update_port(self, context, id, port): + with db_api.CONTEXT_WRITER.using(context): + updated_port = super( + PortHintsExtensionTestPlugin, + self).update_port(context, id, port) + self._process_update_port(context, port['port'], updated_port) + return updated_port + + +@ddt.ddt +class PortHintsExtensionTestCase( + test_db_base_plugin_v2.NeutronDbPluginV2TestCase): + """Test API extension port-hints attributes.""" + + def setUp(self, *args): + plugin = ('neutron.tests.unit.extensions.test_port_hints.' + 'PortHintsExtensionTestPlugin') + super(PortHintsExtensionTestCase, self).setUp(plugin=plugin) + + def _create_and_check_port_hints(self, hints): + keys = [('name', 'name_1'), + ('admin_state_up', True), + ('status', self.port_create_status), + ('hints', hints)] + with self.port(is_admin=True, name='name_1', hints=hints) as port: + for k, v in keys: + self.assertEqual(v, port['port'][k]) + return port + + def _update_and_check_port_hints(self, port, hints): + data = {'port': {'hints': hints}} + req = self.new_update_request( + 'ports', data, port['port']['id'], as_admin=True) + res = self.deserialize(self.fmt, req.get_response(self.api)) + self.assertEqual( + hints, res['port']['hints']) + + @ddt.data(*HINTS_LIST) + def test_create_and_update_port_hints( + self, hints): + port = self._create_and_check_port_hints(hints) + for new_hints in HINTS_LIST: + self._update_and_check_port_hints(port, new_hints) diff --git a/neutron/tests/unit/extensions/test_portsecurity.py b/neutron/tests/unit/extensions/test_portsecurity.py index 027740c2f2..aedd75251d 100644 --- a/neutron/tests/unit/extensions/test_portsecurity.py +++ b/neutron/tests/unit/extensions/test_portsecurity.py @@ -18,7 +18,6 @@ from unittest import mock from neutron_lib.api.definitions import port_security as psec from neutron_lib.api import validators -from neutron_lib import context from neutron_lib.db import api as db_api from neutron_lib.db import utils as db_utils from neutron_lib.exceptions import port_security as psec_exc @@ -311,11 +310,11 @@ class TestPortSecurity(PortSecurityDBTestCase): self.skipTest("Plugin does not support security groups") res = self._create_network('json', 'net1', True, arg_list=('port_security_enabled',), - set_context=True, tenant_id='admin_tenant', port_security_enabled=False) net = self.deserialize('json', res) - self._create_subnet('json', net['network']['id'], '10.0.0.0/24') + self._create_subnet('json', net['network']['id'], '10.0.0.0/24', + tenant_id='admin_tenant') security_group = self.deserialize( 'json', self._create_security_group(self.fmt, 'asdf', 'asdf', tenant_id='other_tenant')) @@ -323,7 +322,6 @@ class TestPortSecurity(PortSecurityDBTestCase): res = self._create_port('json', net['network']['id'], arg_list=('security_groups', 'port_security_enabled'), - set_context=True, is_admin=True, tenant_id='admin_tenant', port_security_enabled=True, @@ -331,19 +329,18 @@ class TestPortSecurity(PortSecurityDBTestCase): port = self.deserialize('json', res) self.assertTrue(port['port'][psec.PORTSECURITY]) self.assertEqual(port['port']['security_groups'], [security_group_id]) - self._delete('ports', port['port']['id']) + self._delete('ports', port['port']['id'], tenant_id='admin_tenant') def test_create_port_with_no_admin_use_other_tenant_security_group(self): if self._skip_security_group: self.skipTest("Plugin does not support security groups") res = self._create_network('json', 'net1', True, arg_list=('port_security_enabled',), - set_context=True, tenant_id='demo_tenant', port_security_enabled=False) net = self.deserialize('json', res) self._create_subnet('json', net['network']['id'], '10.0.0.0/24', - set_context=True, tenant_id='demo_tenant') + tenant_id='demo_tenant') security_group = self.deserialize( 'json', self._create_security_group(self.fmt, 'asdf', 'asdf', tenant_id='other_tenant')) @@ -351,7 +348,6 @@ class TestPortSecurity(PortSecurityDBTestCase): res = self._create_port('json', net['network']['id'], arg_list=('security_groups', 'port_security_enabled'), - set_context=True, tenant_id='demo_tenant', port_security_enabled=True, security_groups=[security_group_id]) @@ -396,7 +392,7 @@ class TestPortSecurity(PortSecurityDBTestCase): with self.network() as net: with self.subnet(network=net): res = self._create_port('json', net['network']['id'], - set_context=True, is_admin=True, + is_admin=True, tenant_id='admin_tenant',) port = self.deserialize('json', res) self.assertTrue(port['port'][psec.PORTSECURITY]) @@ -408,7 +404,9 @@ class TestPortSecurity(PortSecurityDBTestCase): update_port = {'port': {'security_groups': [security_group_id]}} req = self.new_update_request('ports', update_port, - port['port']['id']) + port['port']['id'], + tenant_id='admin_tenant', + as_admin=True) port = self.deserialize('json', req.get_response(self.api)) security_groups = port['port']['security_groups'] self.assertIn(security_group_id, security_groups) @@ -420,7 +418,6 @@ class TestPortSecurity(PortSecurityDBTestCase): with self.network(tenant_id='demo_tenant') as net: with self.subnet(network=net, tenant_id='demo_tenant'): res = self._create_port('json', net['network']['id'], - set_context=True, tenant_id='demo_tenant',) port = self.deserialize('json', res) self.assertTrue(port['port'][psec.PORTSECURITY]) @@ -432,9 +429,8 @@ class TestPortSecurity(PortSecurityDBTestCase): update_port = {'port': {'security_groups': [security_group_id]}} req = self.new_update_request('ports', update_port, - port['port']['id']) - req.environ['neutron.context'] = context.Context( - '', 'other_tenant') + port['port']['id'], + tenant_id='other_tenant') res = req.get_response(self.api) self.assertEqual(404, res.status_int) @@ -490,29 +486,26 @@ class TestPortSecurity(PortSecurityDBTestCase): self._delete('ports', port['port']['id']) def test_create_port_security_off_shared_network(self): - with self.network(shared=True) as net: + with self.network(as_admin=True, shared=True) as net: with self.subnet(network=net): res = self._create_port('json', net['network']['id'], arg_list=('port_security_enabled',), port_security_enabled=False, - tenant_id='not_network_owner', - set_context=True) + tenant_id='not_network_owner') self.deserialize('json', res) self.assertEqual(403, res.status_int) def test_update_port_security_off_shared_network(self): - with self.network(shared=True) as net: + with self.network(as_admin=True, shared=True) as net: with self.subnet(network=net): res = self._create_port('json', net['network']['id'], - tenant_id='not_network_owner', - set_context=True) + tenant_id='not_network_owner') port = self.deserialize('json', res) # remove security group on port update_port = {'port': {ext_sg.SECURITYGROUPS: None, psec.PORTSECURITY: False}} req = self.new_update_request('ports', update_port, - port['port']['id']) - req.environ['neutron.context'] = context.Context( - '', 'not_network_owner') + port['port']['id'], + tenant_id='not_network_owner') res = req.get_response(self.api) self.assertEqual(exc.HTTPForbidden.code, res.status_int) diff --git a/neutron/tests/unit/extensions/test_providernet.py b/neutron/tests/unit/extensions/test_providernet.py index 61e1422aa2..fc40dae6c1 100644 --- a/neutron/tests/unit/extensions/test_providernet.py +++ b/neutron/tests/unit/extensions/test_providernet.py @@ -92,21 +92,28 @@ class ProvidernetExtensionTestCase(testlib_api.WebTestCase): def _put_network_with_provider_attrs(self, ctx, expect_errors=False): data = self._prepare_net_data() + ctx.roles = ['member', 'reader'] + if ctx.is_admin: + ctx.roles.append('admin') env = {'neutron.context': ctx} instance = self.plugin.return_value - instance.get_network.return_value = {'tenant_id': ctx.tenant_id, + instance.get_network.return_value = {'project_id': ctx.tenant_id, 'shared': False} net_id = uuidutils.generate_uuid() res = self.api.put(test_base._get_path('networks', id=net_id, fmt=self.fmt), self.serialize({'network': data}), + content_type='application/' + self.fmt, extra_environ=env, expect_errors=expect_errors) return res, data, net_id def _post_network_with_provider_attrs(self, ctx, expect_errors=False): data = self._prepare_net_data() + ctx.roles = ['member', 'reader'] + if ctx.is_admin: + ctx.roles.append('admin') env = {'neutron.context': ctx} res = self.api.post(test_base._get_path('networks', fmt=self.fmt), self.serialize({'network': data}), @@ -119,6 +126,9 @@ class ProvidernetExtensionTestCase(testlib_api.WebTestCase): expect_errors=False): data = self._prepare_net_data() data.update(bad_data) + ctx.roles = ['member', 'reader'] + if ctx.is_admin: + ctx.roles.append('admin') env = {'neutron.context': ctx} res = self.api.post(test_base._get_path('networks', fmt=self.fmt), self.serialize({'network': data}), diff --git a/neutron/tests/unit/extensions/test_qos_gateway_ip.py b/neutron/tests/unit/extensions/test_qos_gateway_ip.py index 246ed917b3..b8c6b73817 100644 --- a/neutron/tests/unit/extensions/test_qos_gateway_ip.py +++ b/neutron/tests/unit/extensions/test_qos_gateway_ip.py @@ -69,7 +69,7 @@ class GatewayIPQoSDBTestCaseBase(object): ctx = context.get_admin_context() policy_obj = policy.QosPolicy(ctx, id=uuidutils.generate_uuid(), - project_id='tenant', name='pol1', + project_id=self._tenant_id, name='pol1', rules=[]) policy_obj.create() with self.subnet(cidr='11.0.0.0/24') as public_sub,\ @@ -88,7 +88,7 @@ class GatewayIPQoSDBTestCaseBase(object): ctx = context.get_admin_context() policy_obj = policy.QosPolicy(ctx, id=uuidutils.generate_uuid(), - project_id='tenant', name='pol1', + project_id=self._tenant_id, name='pol1', rules=[]) policy_obj.create() with self.subnet(cidr='11.0.0.0/24') as public_sub,\ @@ -115,7 +115,7 @@ class GatewayIPQoSDBTestCaseBase(object): ctx = context.get_admin_context() policy_obj = policy.QosPolicy(ctx, id=uuidutils.generate_uuid(), - project_id='tenant', name='pol1', + project_id=self._tenant_id, name='pol1', rules=[]) policy_obj.create() with self.subnet(cidr='11.0.0.0/24') as public_sub,\ @@ -153,7 +153,7 @@ class GatewayIPQoSDBTestCaseBase(object): ctx = context.get_admin_context() policy_obj = policy.QosPolicy(ctx, id=uuidutils.generate_uuid(), - project_id='tenant', name='pol1', + project_id=self._tenant_id, name='pol1', rules=[]) policy_obj.create() with self.subnet(cidr='11.0.0.0/24') as public_sub,\ diff --git a/neutron/tests/unit/extensions/test_quotasv2.py b/neutron/tests/unit/extensions/test_quotasv2.py index fab52f8be6..c5d914a944 100644 --- a/neutron/tests/unit/extensions/test_quotasv2.py +++ b/neutron/tests/unit/extensions/test_quotasv2.py @@ -120,8 +120,7 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): def test_show_default_quotas_with_admin(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id + '2', - is_admin=True)} + env = test_base._get_neutron_env(project_id + '2', as_admin=True) res = self.api.get(_get_path('quotas', id=project_id, action=DEFAULT_QUOTAS_ACTION, fmt=self.fmt), @@ -137,8 +136,7 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): def test_show_default_quotas_with_owner_project(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id, - is_admin=False)} + env = test_base._get_neutron_env(project_id, as_admin=False) res = self.api.get(_get_path('quotas', id=project_id, action=DEFAULT_QUOTAS_ACTION, fmt=self.fmt), @@ -154,8 +152,7 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): def test_show_default_quotas_without_admin_forbidden_returns_403(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id + '2', - is_admin=False)} + env = test_base._get_neutron_env(project_id + '2', as_admin=False) res = self.api.get(_get_path('quotas', id=project_id, action=DEFAULT_QUOTAS_ACTION, fmt=self.fmt), @@ -164,8 +161,7 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): def test_show_quotas_with_admin(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id + '2', - is_admin=True)} + env = test_base._get_neutron_env(project_id + '2', as_admin=True) res = self.api.get(_get_path('quotas', id=project_id, fmt=self.fmt), extra_environ=env) self.assertEqual(200, res.status_int) @@ -179,16 +175,14 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): def test_show_quotas_without_admin_forbidden_returns_403(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id + '2', - is_admin=False)} + env = test_base._get_neutron_env(project_id + '2', as_admin=False) res = self.api.get(_get_path('quotas', id=project_id, fmt=self.fmt), extra_environ=env, expect_errors=True) self.assertEqual(403, res.status_int) def test_show_quotas_with_owner_project(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id, - is_admin=False)} + env = test_base._get_neutron_env(project_id, as_admin=True) res = self.api.get(_get_path('quotas', id=project_id, fmt=self.fmt), extra_environ=env) self.assertEqual(200, res.status_int) @@ -202,8 +196,7 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): def test_list_quotas_with_admin(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id, - is_admin=True)} + env = test_base._get_neutron_env(project_id, as_admin=True) res = self.api.get(_get_path('quotas', fmt=self.fmt), extra_environ=env) self.assertEqual(200, res.status_int) @@ -212,16 +205,14 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): def test_list_quotas_without_admin_forbidden_returns_403(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id, - is_admin=False)} + env = test_base._get_neutron_env(project_id, as_admin=False) res = self.api.get(_get_path('quotas', fmt=self.fmt), extra_environ=env, expect_errors=True) self.assertEqual(403, res.status_int) def test_update_quotas_without_admin_forbidden_returns_403(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id, - is_admin=False)} + env = test_base._get_neutron_env(project_id, as_admin=False) quotas = {'quota': {'network': 100}} res = self.api.put(_get_path('quotas', id=project_id, fmt=self.fmt), self.serialize(quotas), extra_environ=env, @@ -230,8 +221,7 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): def test_update_quotas_with_non_integer_returns_400(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id, - is_admin=True)} + env = test_base._get_neutron_env(project_id, as_admin=True) quotas = {'quota': {'network': 'abc'}} res = self.api.put(_get_path('quotas', id=project_id, fmt=self.fmt), self.serialize(quotas), extra_environ=env, @@ -240,8 +230,7 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): def test_update_quotas_with_negative_integer_returns_400(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id, - is_admin=True)} + env = test_base._get_neutron_env(project_id, as_admin=True) quotas = {'quota': {'network': -2}} res = self.api.put(_get_path('quotas', id=project_id, fmt=self.fmt), self.serialize(quotas), extra_environ=env, @@ -250,8 +239,7 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): def test_update_quotas_with_out_of_range_integer_returns_400(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id, - is_admin=True)} + env = test_base._get_neutron_env(project_id, as_admin=True) quotas = {'quota': {'network': constants.DB_INTEGER_MAX_VALUE + 1}} res = self.api.put(_get_path('quotas', id=project_id, fmt=self.fmt), self.serialize(quotas), extra_environ=env, @@ -260,8 +248,7 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): def test_update_quotas_to_unlimited(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id, - is_admin=True)} + env = test_base._get_neutron_env(project_id, as_admin=True) quotas = {'quota': {'network': -1}} res = self.api.put(_get_path('quotas', id=project_id, fmt=self.fmt), self.serialize(quotas), extra_environ=env, @@ -270,8 +257,7 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): def test_update_quotas_exceeding_current_limit(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id, - is_admin=True)} + env = test_base._get_neutron_env(project_id, as_admin=True) quotas = {'quota': {'network': 120}} res = self.api.put(_get_path('quotas', id=project_id, fmt=self.fmt), self.serialize(quotas), extra_environ=env, @@ -280,8 +266,7 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): def test_update_quotas_with_non_support_resource_returns_400(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id, - is_admin=True)} + env = test_base._get_neutron_env(project_id, as_admin=True) quotas = {'quota': {'abc': 100}} res = self.api.put(_get_path('quotas', id=project_id, fmt=self.fmt), self.serialize(quotas), extra_environ=env, @@ -290,8 +275,7 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): def test_update_quotas_with_admin(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id + '2', - is_admin=True)} + env = test_base._get_neutron_env(project_id + '2', as_admin=True) quotas = {'quota': {'network': 100}} res = self.api.put(_get_path('quotas', id=project_id, fmt=self.fmt), self.serialize(quotas), extra_environ=env) @@ -306,8 +290,7 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): def test_update_attributes(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id + '2', - is_admin=True)} + env = test_base._get_neutron_env(project_id + '2', as_admin=True) quotas = {'quota': {'extra1': 100}} res = self.api.put(_get_path('quotas', id=project_id, fmt=self.fmt), self.serialize(quotas), extra_environ=env) @@ -321,8 +304,7 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): @mock.patch.object(driver_nolock.DbQuotaNoLockDriver, 'get_resource_usage') def test_update_quotas_check_limit(self, mock_get_resource_usage): tenant_id = 'tenant_id1' - env = {'neutron.context': context.Context('', tenant_id, - is_admin=True)} + env = test_base._get_neutron_env(tenant_id, as_admin=True) quotas = {'quota': {'network': 100, 'check_limit': False}} res = self.api.put(_get_path('quotas', id=tenant_id, fmt=self.fmt), self.serialize(quotas), extra_environ=env, @@ -338,8 +320,7 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): def test_delete_quotas_with_admin(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id + '2', - is_admin=True)} + env = test_base._get_neutron_env(project_id + '2', as_admin=True) # Create a quota to ensure we have something to delete quotas = {'quota': {'network': 100}} self.api.put(_get_path('quotas', id=project_id, fmt=self.fmt), @@ -350,16 +331,14 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): def test_delete_quotas_without_admin_forbidden_returns_403(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id, - is_admin=False)} + env = test_base._get_neutron_env(project_id, as_admin=False) res = self.api.delete(_get_path('quotas', id=project_id, fmt=self.fmt), extra_environ=env, expect_errors=True) self.assertEqual(403, res.status_int) def test_delete_quota_with_unknown_project_returns_404(self): project_id = 'idnotexist' - env = {'neutron.context': context.Context('', project_id + '2', - is_admin=True)} + env = test_base._get_neutron_env(project_id + '2', as_admin=True) res = self.api.delete(_get_path('quotas', id=project_id, fmt=self.fmt), extra_environ=env, expect_errors=True) self.assertEqual(exc.HTTPNotFound.code, res.status_int) @@ -373,8 +352,7 @@ class QuotaExtensionDbTestCase(QuotaExtensionTestCase): def test_quotas_limit_check(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id, - is_admin=True)} + env = test_base._get_neutron_env(project_id, as_admin=True) quotas = {'quota': {'network': 5}} res = self.api.put(_get_path('quotas', id=project_id, fmt=self.fmt), @@ -465,8 +443,7 @@ class QuotaExtensionCfgTestCase(QuotaExtensionTestCase): def test_show_quotas_with_admin(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id + '2', - is_admin=True)} + env = test_base._get_neutron_env(project_id + '2', as_admin=True) res = self.api.get(_get_path('quotas', id=project_id, fmt=self.fmt), extra_environ=env) self.assertEqual(200, res.status_int) @@ -489,8 +466,7 @@ class QuotaExtensionCfgTestCase(QuotaExtensionTestCase): def test_delete_quotas_forbidden(self): project_id = 'project_id1' - env = {'neutron.context': context.Context('', project_id, - is_admin=False)} + env = test_base._get_neutron_env(project_id, as_admin=False) res = self.api.delete(_get_path('quotas', id=project_id, fmt=self.fmt), extra_environ=env, expect_errors=True) self.assertEqual(403, res.status_int) diff --git a/neutron/tests/unit/extensions/test_securitygroup.py b/neutron/tests/unit/extensions/test_securitygroup.py index d0ca88b81a..bbf752e4cb 100644 --- a/neutron/tests/unit/extensions/test_securitygroup.py +++ b/neutron/tests/unit/extensions/test_securitygroup.py @@ -92,41 +92,39 @@ class SecurityGroupTestExtensionManager(object): class SecurityGroupsTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): - def _build_security_group(self, name, description, **kwargs): + def _build_security_group(self, name, description): data = { 'security_group': { 'name': name, - 'tenant_id': kwargs.get( - 'tenant_id', test_db_base_plugin_v2.TEST_TENANT_ID), 'description': description}} return data - def _create_security_group_response(self, fmt, data, **kwargs): - security_group_req = self.new_create_request('security-groups', data, - fmt) - if (kwargs.get('set_context') and 'tenant_id' in kwargs): - # create a specific auth context for this request - security_group_req.environ['neutron.context'] = ( - context.Context('', kwargs['tenant_id'])) + def _create_security_group_response(self, fmt, data, tenant_id=None, + as_admin=False, **kwargs): + security_group_req = self.new_create_request( + 'security-groups', data, fmt, tenant_id=tenant_id, + as_admin=as_admin) return security_group_req.get_response(self.ext_api) - def _create_security_group(self, fmt, name, description, **kwargs): - data = self._build_security_group(name, description, **kwargs) - return self._create_security_group_response(fmt, data, **kwargs) + def _create_security_group(self, fmt, name, description, tenant_id=None, + as_admin=False, **kwargs): + data = self._build_security_group(name, description) + return self._create_security_group_response( + fmt, data, tenant_id=tenant_id, as_admin=as_admin, **kwargs) def _build_security_group_rule( self, security_group_id, direction, proto, port_range_min=None, port_range_max=None, remote_ip_prefix=None, remote_group_id=None, remote_address_group_id=None, - tenant_id=test_db_base_plugin_v2.TEST_TENANT_ID, - ethertype=const.IPv4): + tenant_id=None, + ethertype=const.IPv4, + as_admin=False): data = {'security_group_rule': {'security_group_id': security_group_id, 'direction': direction, 'protocol': proto, - 'ethertype': ethertype, - 'tenant_id': tenant_id}} + 'ethertype': ethertype}} if port_range_min: data['security_group_rule']['port_range_min'] = port_range_min @@ -145,19 +143,13 @@ class SecurityGroupsTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): return data - def _create_security_group_rule(self, fmt, rules, **kwargs): + def _create_security_group_rule(self, fmt, rules, tenant_id=None, + as_admin=False, **kwargs): security_group_rule_req = self.new_create_request( - 'security-group-rules', rules, fmt) - - if (kwargs.get('set_context') and 'tenant_id' in kwargs): - # create a specific auth context for this request - security_group_rule_req.environ['neutron.context'] = ( - context.Context('', kwargs['tenant_id'])) - elif kwargs.get('admin_context'): - security_group_rule_req.environ['neutron.context'] = ( - context.Context(user_id='admin', tenant_id='admin-tenant', - is_admin=True)) + 'security-group-rules', rules, fmt, tenant_id=tenant_id, + as_admin=as_admin) + return security_group_rule_req.get_response(self.ext_api) def _make_security_group(self, fmt, name, description, **kwargs): @@ -166,8 +158,10 @@ class SecurityGroupsTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): raise webob.exc.HTTPClientError(code=res.status_int) return self.deserialize(fmt, res) - def _make_security_group_rule(self, fmt, rules, **kwargs): - res = self._create_security_group_rule(self.fmt, rules) + def _make_security_group_rule(self, fmt, rules, tenant_id=None, + as_admin=False, **kwargs): + res = self._create_security_group_rule( + self.fmt, rules, tenant_id=tenant_id, as_admin=as_admin) if res.status_int >= webob.exc.HTTPBadRequest.code: raise webob.exc.HTTPClientError(code=res.status_int) return self.deserialize(fmt, res) @@ -819,9 +813,10 @@ class TestSecurityGroups(SecurityGroupDBTestCase): sg['security_group']['id'], "ingress", const.PROTO_NAME_TCP, port_range_min=22, port_range_max=22, remote_ip_prefix="10.0.2.0/24", - ethertype=const.IPv4, - tenant_id='admin-tenant') - self._make_security_group_rule(self.fmt, rule, admin_context=True) + ethertype=const.IPv4) + self._make_security_group_rule(self.fmt, rule, + tenant_id='admin-tenant', + as_admin=True) # Now, let's make sure all the rules are there, with their odd # tenant_id behavior. @@ -878,23 +873,20 @@ class TestSecurityGroups(SecurityGroupDBTestCase): res = self.new_list_request('security-groups') sg = self.deserialize(self.fmt, res.get_response(self.ext_api)) self._delete('security-groups', sg['security_groups'][0]['id'], - webob.exc.HTTPNoContent.code) + webob.exc.HTTPNoContent.code, as_admin=True) def test_delete_default_security_group_nonadmin(self): with self.network(): res = self.new_list_request('security-groups') sg = self.deserialize(self.fmt, res.get_response(self.ext_api)) - neutron_context = context.Context( - '', test_db_base_plugin_v2.TEST_TENANT_ID) self._delete('security-groups', sg['security_groups'][0]['id'], webob.exc.HTTPConflict.code, - neutron_context=neutron_context) + tenant_id=test_db_base_plugin_v2.TEST_TENANT_ID) def test_security_group_list_creates_default_security_group(self): - neutron_context = context.Context( - '', test_db_base_plugin_v2.TEST_TENANT_ID) sg = self._list('security-groups', - neutron_context=neutron_context).get('security_groups') + tenant_id=test_db_base_plugin_v2.TEST_TENANT_ID).get( + 'security_groups') self.assertEqual(1, len(sg)) def test_security_group_port_create_creates_default_security_group(self): @@ -2112,13 +2104,15 @@ class TestSecurityGroups(SecurityGroupDBTestCase): with self.security_group() as sg: rule = self._build_security_group_rule( sg['security_group']['id'], 'ingress', const.PROTO_NUM_TCP) - rule['security_group_rule'].update({'id': specified_id, - 'port_range_min': None, - 'port_range_max': None, - 'remote_ip_prefix': None, - 'remote_group_id': None, - 'remote_address_group_id': - None}) + rule['security_group_rule'].update({ + 'id': specified_id, + 'port_range_min': None, + 'port_range_max': None, + 'remote_ip_prefix': None, + 'remote_group_id': None, + 'tenant_id': test_db_base_plugin_v2.TEST_TENANT_ID, + 'remote_address_group_id': + None}) result = self.plugin.create_security_group_rule( neutron_context, rule) self.assertEqual(specified_id, result['id']) diff --git a/neutron/tests/unit/extensions/test_segment.py b/neutron/tests/unit/extensions/test_segment.py index 049205497f..1a3e33e8cf 100644 --- a/neutron/tests/unit/extensions/test_segment.py +++ b/neutron/tests/unit/extensions/test_segment.py @@ -36,6 +36,7 @@ from oslo_config import cfg from oslo_utils import uuidutils import webob.exc +from neutron.common import config from neutron.conf import experimental as c_experimental from neutron.conf.plugins.ml2 import config as ml2_config from neutron.conf.plugins.ml2.drivers import driver_type @@ -81,6 +82,7 @@ class SegmentTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): VLAN_MAX = 209 def setUp(self, plugin=None): + config.register_common_config_options() # Remove MissingAuthPlugin exception from logs self.patch_notifier = mock.patch( 'neutron.notifiers.batch_notifier.BatchNotifier._notify') @@ -112,7 +114,7 @@ class SegmentTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): segment['segment'][k] = None if v is None else str(v) segment_req = self.new_create_request( - 'segments', segment, fmt) + 'segments', segment, fmt, as_admin=True) segment_res = segment_req.get_response(self.ext_api) if expected_res_status: @@ -187,7 +189,8 @@ class TestSegmentNameDescription(SegmentTestCase): result = self._update('segments', segment['segment']['id'], {'segment': {'name': 'Segment name'}}, - expected_code=webob.exc.HTTPOk.code) + expected_code=webob.exc.HTTPOk.code, + as_admin=True) self.assertEqual('Segment name', result['segment']['name']) def test_update_segment_set_description(self): @@ -195,7 +198,8 @@ class TestSegmentNameDescription(SegmentTestCase): result = self._update('segments', segment['segment']['id'], {'segment': {'description': 'Segment desc'}}, - expected_code=webob.exc.HTTPOk.code) + expected_code=webob.exc.HTTPOk.code, + as_admin=True) self.assertEqual('Segment desc', result['segment']['description']) def test_update_segment_set_name_to_none(self): @@ -204,7 +208,8 @@ class TestSegmentNameDescription(SegmentTestCase): result = self._update('segments', segment['segment']['id'], {'segment': {'name': None}}, - expected_code=webob.exc.HTTPOk.code) + expected_code=webob.exc.HTTPOk.code, + as_admin=True) self.assertIsNone(result['segment']['name']) def test_update_segment_set_description_to_none(self): @@ -271,7 +276,8 @@ class TestSegment(SegmentTestCase): with self.network() as network: network = network['network'] - local_segment = self._list('segments')['segments'][0] + local_segment = self._list('segments', + as_admin=True)['segments'][0] with mock.patch.object(registry, 'publish') as publish: publish.side_effect = exceptions.CallbackFailure(errors=Exception) self.assertRaises(webob.exc.HTTPClientError, @@ -310,7 +316,7 @@ class TestSegment(SegmentTestCase): physical_network='physnet0') segment = self.segment(network_id=network['id'], segmentation_id=201, physical_network='physnet1') - self._delete('segments', segment['segment']['id']) + self._delete('segments', segment['segment']['id'], as_admin=True) self._show('segments', segment['segment']['id'], expected_code=webob.exc.HTTPNotFound.code) @@ -324,8 +330,10 @@ class TestSegment(SegmentTestCase): segment_id = segment['segment']['id'] with self.subnet(network=network, segment_id=segment_id): self._delete('segments', segment_id, - expected_code=webob.exc.HTTPConflict.code) - exist_segment = self._show('segments', segment_id) + expected_code=webob.exc.HTTPConflict.code, + as_admin=True) + exist_segment = self._show('segments', segment_id, + as_admin=True) self.assertEqual(segment_id, exist_segment['segment']['id']) def test_get_segment(self): @@ -334,7 +342,8 @@ class TestSegment(SegmentTestCase): segment = self._test_create_segment(network_id=network['id'], physical_network='physnet', segmentation_id=200) - req = self.new_show_request('segments', segment['segment']['id']) + req = self.new_show_request('segments', segment['segment']['id'], + as_admin=True) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) self.assertEqual(segment['segment']['id'], res['segment']['id']) @@ -347,14 +356,15 @@ class TestSegment(SegmentTestCase): self._test_create_segment(network_id=network['id'], physical_network='physnet2', segmentation_id=201) - res = self._list('segments') + res = self._list('segments', as_admin=True) self.assertEqual(3, len(res['segments'])) def test_list_segments_with_sort(self): with self.network() as network: network = network['network'] - local_segment = {'segment': self._list('segments')['segments'][0]} + local_segment = {'segment': self._list('segments', + as_admin=True)['segments'][0]} s1 = self._test_create_segment(network_id=network['id'], physical_network='physnet1', segmentation_id=200) @@ -364,13 +374,15 @@ class TestSegment(SegmentTestCase): self._test_list_with_sort('segment', (s2, s1, local_segment), [('physical_network', 'desc')], - query_params='network_id=%s' % network['id']) + query_params='network_id=%s' % network['id'], + as_admin=True) def test_list_segments_with_pagination(self): with self.network() as network: network = network['network'] - local_segment = {'segment': self._list('segments')['segments'][0]} + local_segment = {'segment': self._list('segments', + as_admin=True)['segments'][0]} s1 = self._test_create_segment(network_id=network['id'], physical_network='physnet0', segmentation_id=200) @@ -384,7 +396,8 @@ class TestSegment(SegmentTestCase): 'segment', (local_segment, s1, s2, s3), ('physical_network', 'asc'), 3, 2, - query_params='network_id=%s' % network['id']) + query_params='network_id=%s' % network['id'], + as_admin=True) def test_list_segments_with_pagination_reverse(self): with self.network() as network: @@ -403,7 +416,8 @@ class TestSegment(SegmentTestCase): 'segment', (s1, s2, s3), ('physical_network', 'asc'), 2, 2, - query_params='network_id=%s' % network['id']) + query_params='network_id=%s' % network['id'], + as_admin=True) def test_update_segments(self): with self.network() as network: @@ -454,7 +468,7 @@ class TestSegmentSubnetAssociation(SegmentTestCase): with self.subnet(network=network, segment_id=segment_id) as subnet: subnet = subnet['subnet'] - request = self.new_show_request('subnets', subnet['id']) + request = self.new_show_request('subnets', subnet['id'], as_admin=True) response = request.get_response(self.api) res = self.deserialize(self.fmt, response) self.assertEqual(segment_id, @@ -554,12 +568,14 @@ class TestSegmentSubnetAssociation(SegmentTestCase): with self.network() as network: pass - segment_id = self._list('segments')['segments'][0]['id'] + segment_id = self._list('segments', + as_admin=True)['segments'][0]['id'] with self.subnet(network=network, segment_id=None) as subnet: subnet = subnet['subnet'] data = {'subnet': {'segment_id': segment_id}} - request = self.new_update_request('subnets', data, subnet['id']) + request = self.new_update_request('subnets', data, subnet['id'], + as_admin=True) response = request.get_response(self.api) res = self.deserialize(self.fmt, response) @@ -580,7 +596,8 @@ class TestSegmentSubnetAssociation(SegmentTestCase): subnet = subnet['subnet'] data = {'subnet': {'segment_id': segment1['id']}} - request = self.new_update_request('subnets', data, subnet['id']) + request = self.new_update_request('subnets', data, subnet['id'], + as_admin=True) response = request.get_response(self.api) res = self.deserialize(self.fmt, response) @@ -602,7 +619,8 @@ class TestSegmentSubnetAssociation(SegmentTestCase): subnet = subnet['subnet'] data = {'subnet': {'segment_id': segment1['id']}} - request = self.new_update_request('subnets', data, subnet['id']) + request = self.new_update_request('subnets', data, subnet['id'], + as_admin=True) response = request.get_response(self.api) self.assertEqual(webob.exc.HTTPBadRequest.code, response.status_int) @@ -625,7 +643,8 @@ class TestSegmentSubnetAssociation(SegmentTestCase): subnet2 = subnet2['subnet'] data = {'subnet': {'segment_id': segment1['id']}} - request = self.new_update_request('subnets', data, subnet1['id']) + request = self.new_update_request('subnets', data, subnet1['id'], + as_admin=True) response = request.get_response(self.api) self.assertEqual(webob.exc.HTTPBadRequest.code, response.status_int) @@ -634,7 +653,7 @@ class TestSegmentSubnetAssociation(SegmentTestCase): with self.network() as network: net = network['network'] - segment_id = self._list('segments')['segments'][0]['id'] + segment_id = self._list('segments', as_admin=True)['segments'][0]['id'] with self.subnet(network=network, segment_id=segment_id) as subnet: subnet = subnet['subnet'] @@ -643,7 +662,8 @@ class TestSegmentSubnetAssociation(SegmentTestCase): segmentation_id=202)['segment'] data = {'subnet': {'segment_id': segment2['id']}} - request = self.new_update_request('subnets', data, subnet['id']) + request = self.new_update_request('subnets', data, subnet['id'], + as_admin=True) response = request.get_response(self.api) self.assertEqual(webob.exc.HTTPBadRequest.code, response.status_int) @@ -853,7 +873,7 @@ class TestMl2HostSegmentMappingOVS(HostSegmentMappingTestCase): def test_segment_deletion_removes_host_mapping(self): host = 'host1' segment = self._test_one_segment_one_host(host) - self._delete('segments', segment['id']) + self._delete('segments', segment['id'], as_admin=True) segments_host_db = self._get_segments_for_host(host) self.assertFalse(segments_host_db) @@ -1019,7 +1039,8 @@ class SegmentAwareIpamTestCase(SegmentTestCase): segment_id=segment['segment']['id'], ip_version=ip_version, cidr=cidr, - allocation_pools=allocation_pools) as subnet: + allocation_pools=allocation_pools, + as_admin=True) as subnet: self._validate_l2_adjacency(network['network']['id'], is_adjacent=False) return subnet @@ -1096,6 +1117,7 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): response = self._create_port(self.fmt, net_id=network['network']['id'], tenant_id=network['network']['tenant_id'], + is_admin=True, fixed_ips=[ {'subnet_id': subnet['subnet']['id']} ]) @@ -1123,6 +1145,7 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): response = self._create_port(self.fmt, net_id=network['network']['id'], tenant_id=network['network']['tenant_id'], + is_admin=True, arg_list=(portbindings.HOST_ID,), **{portbindings.HOST_ID: 'fakehost'}) res = self.deserialize(self.fmt, response) @@ -1145,6 +1168,7 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): response = self._create_port(self.fmt, net_id=network['network']['id'], tenant_id=network['network']['tenant_id'], + is_admin=True, arg_list=(portbindings.HOST_ID,), **{portbindings.HOST_ID: 'fakehost'}) res = self.deserialize(self.fmt, response) @@ -1171,6 +1195,7 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): response = self._create_port(self.fmt, net_id=network['network']['id'], tenant_id=network['network']['tenant_id'], + is_admin=True, arg_list=(portbindings.HOST_ID,), **{portbindings.HOST_ID: 'fakehost'}) @@ -1186,6 +1211,7 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): response = self._create_port(self.fmt, net_id=network['network']['id'], tenant_id=network['network']['tenant_id'], + is_admin=True, arg_list=(portbindings.HOST_ID,), **{portbindings.HOST_ID: 'fakehost'}) res = self.deserialize(self.fmt, response) @@ -1199,6 +1225,7 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): response = self._create_port(self.fmt, net_id=network['network']['id'], tenant_id=network['network']['tenant_id'], + is_admin=True, arg_list=(portbindings.HOST_ID,), **{portbindings.HOST_ID: 'fakehost'}) res = self.deserialize(self.fmt, response) @@ -1218,6 +1245,7 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): response = self._create_port(self.fmt, net_id=network['network']['id'], tenant_id=network['network']['tenant_id'], + is_admin=True, arg_list=(portbindings.HOST_ID,), **{portbindings.HOST_ID: 'fakehost'}) self.deserialize(self.fmt, response) @@ -1280,6 +1308,7 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): self.fmt, net_id=network['network']['id'], tenant_id=network['network']['tenant_id'], + is_admin=True, **kwargs) port = self.deserialize(self.fmt, response) request = self.new_show_request('ports', port['port']['id']) @@ -1324,6 +1353,7 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): response = self._create_port(self.fmt, net_id=network['network']['id'], tenant_id=network['network']['tenant_id'], + is_admin=True, arg_list=(portbindings.HOST_ID,), **{portbindings.HOST_ID: 'fakehost'}) port = self.deserialize(self.fmt, response) @@ -1360,6 +1390,7 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): response = self._create_port(self.fmt, net_id=network['network']['id'], tenant_id=network['network']['tenant_id'], + is_admin=True, arg_list=(portbindings.HOST_ID,), **{portbindings.HOST_ID: 'fakehost'}) port = self.deserialize(self.fmt, response) @@ -1401,7 +1432,8 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): def _create_deferred_ip_port(self, network): response = self._create_port(self.fmt, net_id=network['network']['id'], - tenant_id=network['network']['tenant_id']) + tenant_id=network['network']['tenant_id'], + is_admin=True) port = self.deserialize(self.fmt, response) ips = port['port']['fixed_ips'] self.assertEqual(0, len(ips)) @@ -1421,7 +1453,8 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): # Try requesting an IP (but the only subnet is on a segment) data = {'port': {portbindings.HOST_ID: 'fakehost'}} port_id = port['port']['id'] - port_req = self.new_update_request('ports', data, port_id) + port_req = self.new_update_request('ports', data, port_id, + as_admin=True) response = port_req.get_response(self.api) # Port update succeeds and allocates a new IP address. @@ -1439,7 +1472,8 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): with self.subnet(network=network): data = {'port': {portbindings.HOST_ID: 'fakehost'}} port_id = port['port']['id'] - port_req = self.new_update_request('ports', data, port_id) + port_req = self.new_update_request('ports', data, port_id, + as_admin=True) response = port_req.get_response(self.api) self.assertEqual(webob.exc.HTTPOk.code, response.status_int) @@ -1455,7 +1489,8 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): response = self._create_port(self.fmt, net_id=network['network']['id'], tenant_id=network['network']['tenant_id'], - fixed_ips=[]) + fixed_ips=[], + is_admin=True) port = self.deserialize(self.fmt, response) ips = port['port']['fixed_ips'] self.assertEqual(0, len(ips)) @@ -1463,7 +1498,8 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): # Create the subnet and try to update the port to get an IP data = {'port': {portbindings.HOST_ID: 'fakehost'}} port_id = port['port']['id'] - port_req = self.new_update_request('ports', data, port_id) + port_req = self.new_update_request('ports', data, port_id, + as_admin=True) response = port_req.get_response(self.api) self.assertEqual(webob.exc.HTTPOk.code, response.status_int) @@ -1483,7 +1519,8 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): portbindings.HOST_ID: 'fakehost', 'fixed_ips': [{'subnet_id': subnet['subnet']['id']}]}} port_id = port['port']['id'] - port_req = self.new_update_request('ports', data, port_id) + port_req = self.new_update_request('ports', data, port_id, + as_admin=True) response = port_req.get_response(self.api) self.assertEqual(webob.exc.HTTPOk.code, response.status_int) @@ -1508,7 +1545,8 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): portbindings.HOST_ID: 'fakehost', 'fixed_ips': []}} port_id = port['port']['id'] - port_req = self.new_update_request('ports', data, port_id) + port_req = self.new_update_request('ports', data, port_id, + as_admin=True) response = port_req.get_response(self.api) self.assertEqual(webob.exc.HTTPOk.code, response.status_int) @@ -1526,7 +1564,8 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): # Try requesting an IP (but the only subnet is on a segment) data = {'port': {portbindings.HOST_ID: 'fakehost'}} port_id = port['port']['id'] - port_req = self.new_update_request('ports', data, port_id) + port_req = self.new_update_request('ports', data, port_id, + as_admin=True) response = port_req.get_response(self.api) res = self.deserialize(self.fmt, response) @@ -1549,7 +1588,8 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): # Try requesting an IP (but the only subnet is on a segment) data = {'port': {portbindings.HOST_ID: 'fakehost'}} port_id = port['port']['id'] - port_req = self.new_update_request('ports', data, port_id) + port_req = self.new_update_request('ports', data, port_id, + as_admin=True) response = port_req.get_response(self.api) self.deserialize(self.fmt, response) @@ -1597,7 +1637,8 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): # Try requesting an IP (but the subnet ran out of ips) data = {'port': {portbindings.HOST_ID: 'fakehost'}} port_id = port['port']['id'] - port_req = self.new_update_request('ports', data, port_id) + port_req = self.new_update_request('ports', data, port_id, + as_admin=True) response = port_req.get_response(self.api) res = self.deserialize(self.fmt, response) @@ -1617,6 +1658,7 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): response = self._create_port(self.fmt, net_id=network['network']['id'], tenant_id=network['network']['tenant_id'], + is_admin=True, arg_list=(portbindings.HOST_ID,), **{portbindings.HOST_ID: 'fakehost'}) self._assert_one_ip_in_subnet(response, subnets[1]['subnet']['cidr']) @@ -1624,7 +1666,8 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): # Now, try to update binding to a host on the other segment data = {'port': {portbindings.HOST_ID: 'fakehost2'}} - port_req = self.new_update_request('ports', data, port['port']['id']) + port_req = self.new_update_request('ports', data, port['port']['id'], + as_admin=True) response = port_req.get_response(self.api) # It fails since the IP address isn't compatible with the new segment @@ -1642,6 +1685,7 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): response = self._create_port(self.fmt, net_id=network['network']['id'], tenant_id=network['network']['tenant_id'], + is_admin=True, arg_list=(portbindings.HOST_ID,), **{portbindings.HOST_ID: 'fakehost'}) self._assert_one_ip_in_subnet(response, subnets[1]['subnet']['cidr']) @@ -1649,7 +1693,8 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): # Now, try to update binding to another host in same segment data = {'port': {portbindings.HOST_ID: 'fakehost1'}} - port_req = self.new_update_request('ports', data, port['port']['id']) + port_req = self.new_update_request('ports', data, port['port']['id'], + as_admin=True) response = port_req.get_response(self.api) # Since the new host is in the same segment, it succeeds. @@ -1669,7 +1714,8 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): data = {'port': {portbindings.HOST_ID: 'fakehost', port_apidef.PORT_MAC_ADDRESS: '00:00:00:00:00:01'}} port_id = port['port']['id'] - port_req = self.new_update_request('ports', data, port_id) + port_req = self.new_update_request('ports', data, port_id, + as_admin=True) response = port_req.get_response(self.api) # Port update succeeds and allocates a new IP address. @@ -1720,6 +1766,7 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase): response = self._create_port(self.fmt, net_id=network['network']['id'], tenant_id=network['network']['tenant_id'], + is_admin=True, arg_list=(portbindings.HOST_ID,), **{portbindings.HOST_ID: 'fakehost_a'}) res = self.deserialize(self.fmt, response) @@ -1847,7 +1894,8 @@ class TestSegmentAwareIpamML2(TestSegmentAwareIpam): network, segment, subnet = self._create_test_segment_with_subnet() self.assertTrue(self.VLAN_MIN <= segment['segment']['segmentation_id'] <= self.VLAN_MAX) - retrieved_segment = self._show('segments', segment['segment']['id']) + retrieved_segment = self._show('segments', segment['segment']['id'], + as_admin=True) self.assertEqual(segment['segment']['segmentation_id'], retrieved_segment['segment']['segmentation_id']) @@ -1973,7 +2021,8 @@ class TestNovaSegmentNotifier(SegmentAwareIpamTestCase): def test_update_subnet_association_with_segment(self, cidr='10.0.0.0/24', allocation_pools=None): with self.network() as network: - segment_id = self._list('segments')['segments'][0]['id'] + segment_id = self._list('segments', + as_admin=True)['segments'][0]['id'] network_id = network['network']['id'] self._setup_host_mappings([(segment_id, 'fakehost')]) @@ -1991,9 +2040,11 @@ class TestNovaSegmentNotifier(SegmentAwareIpamTestCase): segment_id=None) as subnet: self._validate_l2_adjacency(network_id, is_adjacent=True) data = {'subnet': {'segment_id': segment_id}} - self.new_update_request('subnets', data, subnet['subnet']['id']) + self.new_update_request('subnets', data, subnet['subnet']['id'], + as_admin=True) self.new_update_request( - 'subnets', data, subnet['subnet']['id']).get_response(self.api) + 'subnets', data, subnet['subnet']['id'], + as_admin=True).get_response(self.api) self._validate_l2_adjacency(network_id, is_adjacent=False) self._assert_inventory_creation(segment_id, aggregate, subnet) @@ -2285,7 +2336,8 @@ class TestNovaSegmentNotifier(SegmentAwareIpamTestCase): def _create_test_port(self, network_id, tenant_id, subnet, **kwargs): port = self._make_port(self.fmt, network_id, tenant_id=tenant_id, - arg_list=(portbindings.HOST_ID,), **kwargs) + as_admin=True, arg_list=(portbindings.HOST_ID,), + **kwargs) self.batch_notifier._notify() return port @@ -2401,7 +2453,7 @@ class TestNovaSegmentNotifier(SegmentAwareIpamTestCase): if compute_owned: port_data['port']['device_owner'] = ( constants.DEVICE_OWNER_COMPUTE_PREFIX) - self._update('ports', port['port']['id'], port_data) + self._update('ports', port['port']['id'], port_data, as_admin=True) self.batch_notifier._notify() self._assert_inventory_update_port( first_subnet['subnet']['segment_id'], original_inventory, diff --git a/neutron/tests/unit/extensions/test_servicetype.py b/neutron/tests/unit/extensions/test_servicetype.py index 7552b8a86a..5af9c14ac3 100644 --- a/neutron/tests/unit/extensions/test_servicetype.py +++ b/neutron/tests/unit/extensions/test_servicetype.py @@ -25,6 +25,7 @@ import webob.exc as webexc import webtest from neutron.api import extensions +from neutron.common import config from neutron.db import servicetype_db as st_db from neutron.extensions import servicetype from neutron.objects import servicetype as servicetype_obj @@ -48,6 +49,7 @@ class ServiceTypeManagerTestCase(testlib_api.SqlTestCase): provconf.NeutronModule, 'service_providers').start() super(ServiceTypeManagerTestCase, self).setUp() self.ctx = context.get_admin_context() + config.register_common_config_options() self.setup_coreplugin(PLUGIN_NAME) def _set_override(self, service_providers): @@ -192,6 +194,7 @@ class ServiceTypeExtensionTestCaseBase(testlib_api.WebTestCase): def setUp(self): # This is needed because otherwise a failure will occur due to # nonexisting core_plugin + config.register_common_config_options() self.setup_coreplugin(test_db_base_plugin_v2.DB_PLUGIN_KLASS) cfg.CONF.set_override('service_plugins', @@ -248,7 +251,8 @@ class ServiceTypeManagerExtTestCase(ServiceTypeExtensionTestCaseBase): super(ServiceTypeManagerExtTestCase, self).setUp() def _list_service_providers(self): - return self.api.get(_get_path('service-providers', fmt=self.fmt)) + return self.api.get(_get_path('service-providers', fmt=self.fmt), + extra_environ=test_base._get_neutron_env()) def test_list_service_providers(self): res = self._list_service_providers() diff --git a/neutron/tests/unit/extensions/test_subnet_onboard.py b/neutron/tests/unit/extensions/test_subnet_onboard.py index bc81600349..d0471ee57e 100644 --- a/neutron/tests/unit/extensions/test_subnet_onboard.py +++ b/neutron/tests/unit/extensions/test_subnet_onboard.py @@ -37,7 +37,7 @@ class SubnetOnboardTestsBase(object): tenant_id = project_id if project_id else kwargs.get( 'tenant_id', None) if not tenant_id: - tenant_id = _uuid() + tenant_id = self._tenant_id scope_data = {'tenant_id': tenant_id, 'ip_version': ip_version, 'shared': shared, 'name': name + '-scope'} @@ -53,7 +53,7 @@ class SubnetOnboardTestsBase(object): tenant_id = project_id if project_id else kwargs.get( 'tenant_id', None) if not tenant_id: - tenant_id = _uuid() + tenant_id = self._tenant_id pool_data = {'tenant_id': tenant_id, 'shared': shared, 'name': name, 'address_scope_id': address_scope_id, 'prefixes': prefixes, 'is_default': is_default_pool} diff --git a/neutron/tests/unit/extensions/test_subnet_service_types.py b/neutron/tests/unit/extensions/test_subnet_service_types.py index a086ebef74..2d2e5c0c28 100644 --- a/neutron/tests/unit/extensions/test_subnet_service_types.py +++ b/neutron/tests/unit/extensions/test_subnet_service_types.py @@ -344,13 +344,14 @@ class SubnetServiceTypesExtensionTestCase( tenant_id=network['tenant_id'], device_owner=service_type, arg_list=(portbindings.HOST_ID,), - **{portbindings.HOST_ID: 'fakehost'}) + **{portbindings.HOST_ID: 'fakehost'}, + is_admin=True) port = self.deserialize('json', port)['port'] # Update the port's host binding. data = {'port': {portbindings.HOST_ID: 'fakehost2'}} # self._update will fail with a MismatchError if the update cannot be # applied - port = self._update('ports', port['id'], data) + port = self._update('ports', port['id'], data, as_admin=True) class SubnetServiceTypesExtensionTestCasev6( diff --git a/neutron/tests/unit/extensions/test_subnetpool_prefix_ops.py b/neutron/tests/unit/extensions/test_subnetpool_prefix_ops.py index 84e38073f5..01ef193be4 100644 --- a/neutron/tests/unit/extensions/test_subnetpool_prefix_ops.py +++ b/neutron/tests/unit/extensions/test_subnetpool_prefix_ops.py @@ -36,7 +36,7 @@ class SubnetpoolPrefixOpsTestBase(object): tenant_id = project_id if project_id else kwargs.get( 'tenant_id', None) if not tenant_id: - tenant_id = _uuid() + tenant_id = self._tenant_id scope_data = {'tenant_id': tenant_id, 'ip_version': ip_version, 'shared': shared, 'name': name + '-scope'} @@ -52,7 +52,7 @@ class SubnetpoolPrefixOpsTestBase(object): tenant_id = project_id if project_id else kwargs.get( 'tenant_id', None) if not tenant_id: - tenant_id = _uuid() + tenant_id = self._tenant_id pool_data = {'tenant_id': tenant_id, 'shared': shared, 'name': name, 'address_scope_id': address_scope_id, 'prefixes': prefixes, 'is_default': is_default_pool} diff --git a/neutron/tests/unit/fake_resources.py b/neutron/tests/unit/fake_resources.py index 2e2737fe63..ca745f6b64 100644 --- a/neutron/tests/unit/fake_resources.py +++ b/neutron/tests/unit/fake_resources.py @@ -163,6 +163,7 @@ class FakeOvsdbNbOvnIdl(object): self.ha_chassis_group_del = mock.Mock() self.ha_chassis_group_add_chassis = mock.Mock() self.ha_chassis_group_del_chassis = mock.Mock() + self.get_lrouter_gw_ports = mock.Mock() class FakeOvsdbSbOvnIdl(object): @@ -321,6 +322,7 @@ class FakeNetwork(object): 'availability_zone_hints': [], 'is_default': False, 'standard_attr_id': 1, + 'mtu': 1500, } # Overwrite default attributes. diff --git a/neutron/tests/unit/objects/port/extensions/test_port_hints.py b/neutron/tests/unit/objects/port/extensions/test_port_hints.py new file mode 100644 index 0000000000..2efd985388 --- /dev/null +++ b/neutron/tests/unit/objects/port/extensions/test_port_hints.py @@ -0,0 +1,33 @@ +# Copyright 2023 Ericsson Software Technology +# +# 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. + +from neutron.objects.port.extensions import port_hints +from neutron.tests.unit.objects import test_base as obj_test_base +from neutron.tests.unit import testlib_api + + +class PortHintsIfaceObjectTestCase(obj_test_base.BaseObjectIfaceTestCase): + + _test_class = port_hints.PortHints + + +class PortHintsDbObjectTestCase( + obj_test_base.BaseDbObjectTestCase, testlib_api.SqlTestCase): + + _test_class = port_hints.PortHints + + def setUp(self): + super(PortHintsDbObjectTestCase, self).setUp() + self.update_obj_fields( + {'port_id': lambda: self._create_test_port_id()}) diff --git a/neutron/tests/unit/objects/test_base.py b/neutron/tests/unit/objects/test_base.py index 4c7a4692d0..6a14951ec3 100644 --- a/neutron/tests/unit/objects/test_base.py +++ b/neutron/tests/unit/objects/test_base.py @@ -55,6 +55,7 @@ from neutron.objects import router from neutron.objects import securitygroup from neutron.objects import stdattrs from neutron.objects import subnet +from neutron.objects import subnetpool from neutron.tests import base as test_base from neutron.tests import tools from neutron.tests.unit.db import test_db_base_plugin_v2 @@ -1583,7 +1584,7 @@ class BaseDbObjectTestCase(_BaseObjectTestCase, fip_obj.create() return fip_obj.id - def _create_test_subnet_id(self, network_id=None): + def _create_test_subnet_id(self, network_id=None, subnet_pool_id=None): if not network_id: network_id = self._create_test_network_id() test_subnet = { @@ -1597,6 +1598,8 @@ class BaseDbObjectTestCase(_BaseObjectTestCase, 'ipv6_ra_mode': None, 'ipv6_address_mode': None } + if subnet_pool_id: + test_subnet['subnetpool_id'] = subnet_pool_id subnet_obj = subnet.Subnet(self.context, **test_subnet) subnet_obj.create() return subnet_obj.id @@ -1722,6 +1725,21 @@ class BaseDbObjectTestCase(_BaseObjectTestCase, _qos_policy.create() return _qos_policy + def _create_test_subnet_pool( + self, prefix, default_prefixlen, min_prefixlen, max_prefixlen, + ip_version): + subnet_pool = { + 'prefixes': [prefix], + 'default_prefixlen': default_prefixlen, + 'min_prefixlen': min_prefixlen, + 'max_prefixlen': max_prefixlen, + 'ip_version': ip_version, + 'address_scope_id': uuidutils.generate_uuid(), + } + subnet_pool_obj = subnetpool.SubnetPool(self.context, **subnet_pool) + subnet_pool_obj.create() + return subnet_pool_obj.id, subnet_pool_obj.address_scope_id + def test_get_standard_attr_id(self): if not self._test_class.has_standard_attributes(): diff --git a/neutron/tests/unit/objects/test_objects.py b/neutron/tests/unit/objects/test_objects.py index d6a431e108..d198bae2b7 100644 --- a/neutron/tests/unit/objects/test_objects.py +++ b/neutron/tests/unit/objects/test_objects.py @@ -73,8 +73,9 @@ object_data = { 'NetworkSegment': '1.0-57b7f2960971e3b95ded20cbc59244a8', 'NetworkSegmentRange': '1.0-bdec1fffc9058ea676089b1f2f2b3cf3', 'NetworkSubnetLock': '1.0-140de39d4b86ae346dc3d70b885bea53', - 'Port': '1.7-d8c1cfe42cfa3719a5d810eeab79e006', + 'Port': '1.8-1aa850ab5529128de07e82c6fb75fcb5', 'PortDeviceProfile': '1.0-b98c7083cc3e93d176fd7a91ae13af32', + 'PortHints': '1.0-9ebf6e12fa427809476a92c7432352b8', 'PortNumaAffinityPolicy': '1.0-38fcea43e7bfb2536461f3d053c43aa3', 'PortBinding': '1.0-3306deeaa6deb01e33af06777d48d578', 'PortBindingLevel': '1.1-50d47f63218f87581b6cd9a62db574e5', diff --git a/neutron/tests/unit/objects/test_ports.py b/neutron/tests/unit/objects/test_ports.py index b01fb998ed..f38077d8d0 100644 --- a/neutron/tests/unit/objects/test_ports.py +++ b/neutron/tests/unit/objects/test_ports.py @@ -529,6 +529,12 @@ class PortDbObjectTestCase(obj_test_base.BaseDbObjectTestCase, self.assertNotIn('device_profile', port_v1_6['versioned_object.data']) + def test_v1_8_to_v1_7_drops_hints(self): + port_new = self._create_test_port() + port_v1_7 = port_new.obj_to_primitive(target_version='1.7') + self.assertNotIn('hints', + port_v1_7['versioned_object.data']) + def test_get_ports_ids_by_security_groups_except_router(self): sg_id = self._create_test_security_group_id() filter_owner = constants.ROUTER_INTERFACE_OWNERS_SNAT diff --git a/neutron/tests/unit/objects/test_router.py b/neutron/tests/unit/objects/test_router.py index 5c86aec2fc..8dff212e49 100644 --- a/neutron/tests/unit/objects/test_router.py +++ b/neutron/tests/unit/objects/test_router.py @@ -17,6 +17,7 @@ from unittest import mock import netaddr +from neutron_lib import constants from neutron_lib.db import api as db_api from oslo_utils import uuidutils @@ -206,6 +207,36 @@ class RouterPortDbObjectTestCase(obj_test_base.BaseDbObjectTestCase, {'router_id': lambda: self._create_test_router_id(), 'port_id': lambda: self._create_test_port_id()}) + def test_get_gw_port_ids_by_router_id(self): + router_id = self._create_test_router_id() + router_gws = [ + self._make_object({ + 'router_id': router_id, + 'port_id': self._create_test_port_id( + device_owner=constants.DEVICE_OWNER_ROUTER_GW), + 'port_type': constants.DEVICE_OWNER_ROUTER_GW}), + self._make_object({ + 'router_id': router_id, + 'port_id': self._create_test_port_id( + device_owner=constants.DEVICE_OWNER_ROUTER_GW), + 'port_type': constants.DEVICE_OWNER_ROUTER_GW, + }) + ] + for gw in router_gws: + gw.create() + + other = self._make_object({ + 'router_id': router_id, + 'port_id': self._create_test_port_id( + device_owner=constants.DEVICE_OWNER_ROUTER_INTF), + 'port_type': constants.DEVICE_OWNER_ROUTER_INTF, + }) + other.create() + + res_gws = self._test_class.get_gw_port_ids_by_router_id(self.context, + router_id) + self.assertCountEqual(res_gws, [rp.port_id for rp in router_gws]) + class DVRMacAddressIfaceObjectTestCase(obj_test_base.BaseObjectIfaceTestCase): @@ -298,17 +329,19 @@ class FloatingIPDbObjectTestCase(obj_test_base.BaseDbObjectTestCase, def test_get_scoped_floating_ips(self): def compare_results(router_ids, original_fips): - self.assertCountEqual( - original_fips, - [ - fip[0].id - for fip in router.FloatingIP.get_scoped_floating_ips( - self.context, router_ids) - ] - ) + fips_scope = [fip for fip in + router.FloatingIP.get_scoped_floating_ips( + self.context, router_ids)] + fip_ids = [fip[0].id for fip in fips_scope] + as_ids = {fip[1] for fip in fips_scope} + self.assertCountEqual(original_fips, fip_ids) + self.assertEqual(1, len(as_ids)) + self.assertEqual(address_scope_id, as_ids.pop()) # Setup three routers, networks and external networks routers = {} + subnet_pool_id, address_scope_id = self._create_test_subnet_pool( + '10.0.0.0/16', 24, 16, 28, constants.IP_VERSION_4) for i in range(3): router_id = self._create_test_router_id(name=f'router-{i}') routers[router_id] = [] @@ -318,7 +351,8 @@ class FloatingIPDbObjectTestCase(obj_test_base.BaseDbObjectTestCase, # Create three subnets and three FIPs using the # aforementioned networks and routers for j in range(3): - self._create_test_subnet_id(net_id) + self._create_test_subnet_id(network_id=net_id, + subnet_pool_id=subnet_pool_id) fip = router.FloatingIP( self.context, floating_ip_address=netaddr.IPAddress(f'10.{i}.{j}.3'), diff --git a/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py b/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py index ef694a059e..b1be2da6f9 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py +++ b/neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py @@ -78,6 +78,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): net_arg = {pnet.NETWORK_TYPE: 'vxlan', pnet.SEGMENTATION_ID: '1'} self._network = self._make_network(self.fmt, 'net1', True, + as_admin=True, arg_list=(pnet.NETWORK_TYPE, pnet.SEGMENTATION_ID,), **net_arg) @@ -86,6 +87,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): pnet.PHYSICAL_NETWORK: 'physnet1', pnet.SEGMENTATION_ID: '2'} self._network2 = self._make_network(self.fmt, 'net2', True, + as_admin=True, arg_list=(pnet.NETWORK_TYPE, pnet.PHYSICAL_NETWORK, pnet.SEGMENTATION_ID,), @@ -94,6 +96,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): net_arg = {pnet.NETWORK_TYPE: 'flat', pnet.PHYSICAL_NETWORK: 'noagent'} self._network3 = self._make_network(self.fmt, 'net3', True, + as_admin=True, arg_list=(pnet.NETWORK_TYPE, pnet.PHYSICAL_NETWORK,), **net_arg) @@ -299,6 +302,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): host_arg = {portbindings.HOST_ID: HOST_4, 'admin_state_up': True} with self.port(subnet=snet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port1: @@ -329,6 +333,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): with self.subnet(network=self._network, enable_dhcp=False) as snet: host_arg = {portbindings.HOST_ID: HOST, 'admin_state_up': True} with self.port(subnet=snet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port1: @@ -357,6 +362,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): with self.subnet(network=self._network, enable_dhcp=False) as snet: with self.port( + is_admin=True, subnet=snet, project_id=self.tenant, device_owner=constants.DEVICE_OWNER_DVR_INTERFACE)\ @@ -365,8 +371,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): plugin.update_distributed_port_binding(self.adminContext, port_id, {'port': {portbindings.HOST_ID: HOST_4, 'device_id': router['id']}}) - port = self._show('ports', port_id, - neutron_context=self.adminContext) + port = self._show('ports', port_id, as_admin=True) self.assertEqual(portbindings.VIF_TYPE_DISTRIBUTED, port['port'][portbindings.VIF_TYPE]) self.callbacks.update_device_up(self.adminContext, @@ -388,6 +393,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): with self.subnet(network=self._network, enable_dhcp=False) as snet: host_arg = {portbindings.HOST_ID: HOST_4, 'admin_state_up': True} with self.port(subnet=snet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port1: @@ -423,6 +429,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): with self.subnet(network=self._network, enable_dhcp=False) as snet: host_arg = {portbindings.HOST_ID: HOST_4, 'admin_state_up': True} with self.port(subnet=snet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port1: @@ -478,10 +485,12 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): with self.subnet(network=self._network) as subnet: host_arg = {portbindings.HOST_ID: HOST} with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port1: with self.port(subnet=subnet, + is_admin=True, arg_list=(portbindings.HOST_ID,), **host_arg): p1 = port1['port'] @@ -512,9 +521,11 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): with self.subnet(network=self._network) as subnet: host_arg = {portbindings.HOST_ID: HOST + '_3'} with self.port(subnet=subnet, + is_admin=True, arg_list=(portbindings.HOST_ID,), **host_arg) as port1: with self.port(subnet=subnet, + is_admin=True, arg_list=(portbindings.HOST_ID,), **host_arg): p1 = port1['port'] @@ -535,10 +546,12 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): with self.subnet(network=self._network2) as subnet: host_arg = {portbindings.HOST_ID: host} with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port1: with self.port(subnet=subnet, + is_admin=True, arg_list=(portbindings.HOST_ID,), **host_arg): p1 = port1['port'] @@ -569,11 +582,13 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): with self.subnet(network=self._network) as subnet: host_arg = {portbindings.HOST_ID: HOST} with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port1: host_arg = {portbindings.HOST_ID: HOST + '_2'} with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg): @@ -610,12 +625,14 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): host_arg = {portbindings.HOST_ID: HOST, 'admin_state_up': True} with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID, 'admin_state_up',), **host_arg) as port1: host_arg = {portbindings.HOST_ID: HOST + '_2', 'admin_state_up': True} with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID, 'admin_state_up',), @@ -669,16 +686,19 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): with self.subnet(network=self._network) as subnet: host_arg = {portbindings.HOST_ID: HOST + '_2'} with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port1: with self.subnet(cidr='10.1.0.0/24') as subnet2: with self.port(subnet=subnet2, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg): host_arg = {portbindings.HOST_ID: HOST} with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port3: @@ -742,6 +762,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): ipv6_address_mode=constants.IPV6_SLAAC) as subnet2: with self.port( subnet, + is_admin=True, fixed_ips=[{'subnet_id': subnet['subnet']['id']}, {'subnet_id': subnet2['subnet']['id']}], device_owner=DEVICE_OWNER_COMPUTE, @@ -783,10 +804,12 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): host_arg = {portbindings.HOST_ID: HOST} # 2 ports on host 1 with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port1: with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port2: @@ -794,6 +817,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): # agent on host 1 host_arg = {portbindings.HOST_ID: HOST + '_2'} with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port3: @@ -833,10 +857,12 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): with self.subnet(network=self._network) as subnet: host_arg = {portbindings.HOST_ID: HOST} with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port1: with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port2: @@ -877,10 +903,12 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): with self.subnet(network=self._network) as subnet: host_arg = {portbindings.HOST_ID: HOST} with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg): with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port2: @@ -919,6 +947,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): host_arg = {portbindings.HOST_ID: HOST_4, 'admin_state_up': True} with self.port(subnet=snet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port1: @@ -954,6 +983,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): with self.subnet(network=self._network) as subnet: host_arg = {portbindings.HOST_ID: HOST} with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port: @@ -966,6 +996,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): device=device) with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port2: @@ -995,10 +1026,12 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): with self.subnet(network=self._network) as subnet: host_arg = {portbindings.HOST_ID: HOST} with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg): with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port: @@ -1029,6 +1062,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): with self.subnet(network=self._network) as subnet: host_arg = {portbindings.HOST_ID: HOST + '_5'} with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port1: @@ -1043,7 +1077,8 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): new_mac = ':'.join(mac) data = {'port': {'mac_address': new_mac, portbindings.HOST_ID: HOST}} - req = self.new_update_request('ports', data, p1['id']) + req = self.new_update_request('ports', data, p1['id'], + as_admin=True) res = self.deserialize(self.fmt, req.get_response(self.api)) self.assertIn('port', res) self.assertEqual(new_mac, res['port']['mac_address']) @@ -1080,6 +1115,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): fixed_ips = [{'subnet_id': subnet['subnet']['id'], 'ip_address': '10.0.0.2'}] with self.port(subnet=subnet, cidr='10.0.0.0/24', + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), fixed_ips=fixed_ips, @@ -1094,7 +1130,8 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): data = {'port': {'fixed_ips': [{'ip_address': '10.0.0.2'}, {'ip_address': '10.0.0.10'}]}} - self.new_update_request('ports', data, p['id']) + self.new_update_request('ports', data, p['id'], + as_admin=True) l2pop_mech = l2pop_mech_driver.L2populationMechanismDriver() l2pop_mech.L2PopulationAgentNotify = mock.Mock() l2notify = l2pop_mech.L2PopulationAgentNotify @@ -1109,6 +1146,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): fixed_ips = [{'subnet_id': subnet['subnet']['id'], 'ip_address': '10.0.0.2'}] with self.port(subnet=subnet, cidr='10.0.0.0/24', + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), fixed_ips=fixed_ips, @@ -1125,7 +1163,8 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): data = {'port': {'fixed_ips': [{'ip_address': '10.0.0.2'}, {'ip_address': '10.0.0.10'}]}} - req = self.new_update_request('ports', data, p1['id']) + req = self.new_update_request('ports', data, p1['id'], + as_admin=True) res = self.deserialize(self.fmt, req.get_response(self.api)) ips = res['port']['fixed_ips'] self.assertEqual(2, len(ips)) @@ -1143,7 +1182,8 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): data = {'port': {'fixed_ips': [{'ip_address': '10.0.0.2'}, {'ip_address': '10.0.0.16'}]}} - req = self.new_update_request('ports', data, p1['id']) + req = self.new_update_request('ports', data, p1['id'], + as_admin=True) res = self.deserialize(self.fmt, req.get_response(self.api)) ips = res['port']['fixed_ips'] self.assertEqual(2, len(ips)) @@ -1162,7 +1202,8 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): self.mock_fanout.reset_mock() data = {'port': {'fixed_ips': [{'ip_address': '10.0.0.16'}]}} - req = self.new_update_request('ports', data, p1['id']) + req = self.new_update_request('ports', data, p1['id'], + as_admin=True) res = self.deserialize(self.fmt, req.get_response(self.api)) ips = res['port']['fixed_ips'] self.assertEqual(1, len(ips)) @@ -1182,6 +1223,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): with self.subnet(network=self._network) as subnet: host_arg = {portbindings.HOST_ID: HOST} with self.port(subnet=subnet, cidr='10.0.0.0/24', + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port1: @@ -1204,6 +1246,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): self._register_ml2_agents() host_arg = {portbindings.HOST_ID: HOST} with self.port(arg_list=(portbindings.HOST_ID,), + is_admin=True, **host_arg) as port: port_id = port['port']['id'] # ensure various formats all result in correct port_id @@ -1217,7 +1260,8 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): def _update_and_check_portbinding(self, port_id, host_id): data = {'port': {portbindings.HOST_ID: host_id}} - req = self.new_update_request('ports', data, port_id) + req = self.new_update_request('ports', data, port_id, + as_admin=True) res = self.deserialize(self.fmt, req.get_response(self.api)) self.assertEqual(host_id, res['port'][portbindings.HOST_ID]) @@ -1227,6 +1271,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): with self.subnet(network=self._network) as subnet: host_arg = {portbindings.HOST_ID: HOST} with self.port(subnet=subnet, cidr='10.0.0.0/24', + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=(portbindings.HOST_ID,), **host_arg) as port1: @@ -1326,6 +1371,7 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase): with self.subnet(network=self._network, enable_dhcp=False) as snet: host_arg = {portbindings.HOST_ID: HOST, 'admin_state_up': True} with self.port(subnet=snet, + is_admin=True, device_owner=constants.DEVICE_OWNER_ROUTER_SNAT, arg_list=(portbindings.HOST_ID,), **host_arg) as p: diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_agent_extension_api.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_agent_extension_api.py index 50897a8772..f8a5643f3a 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_agent_extension_api.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_agent_extension_api.py @@ -68,6 +68,14 @@ class TestOVSAgentExtensionAPI(ovs_test_base.OVSOSKenTestBase): for phys_br in agent_extension_api.request_phy_brs(): self._test_bridge(self.br_phys[phys_br.br_name], phys_br) + def test_request_physical_br(self): + agent_extension_api = ovs_ext_agt.OVSAgentExtensionAPI( + self.br_int, self.br_tun, + {'phys1': self.br_phys['br-phys1'], + 'phys2': self.br_phys['br-phys2']}) + phys_br = agent_extension_api.request_physical_br('phys1') + self._test_bridge(self.br_phys[phys_br.br_name], phys_br) + class TestOVSCookieBridgeOSKen(native_ovs_bridge_test_base.OVSBridgeTestBase): 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 587d3c8e1c..8ddb24d9e2 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 @@ -149,6 +149,7 @@ class TestOvsNeutronAgent(object): mock.patch('neutron.agent.ovsdb.impl_idl._connection').start() self.agent = self._make_agent() self.agent.sg_agent = mock.Mock() + self.agent.ovs_restarted = False def _make_agent(self): with mock.patch.object(self.mod_agent.OVSNeutronAgent, diff --git a/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_commands.py b/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_commands.py index 39bf2a2334..864099f3b8 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_commands.py +++ b/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_commands.py @@ -1214,6 +1214,7 @@ class TestDeleteLRouterExtGwCommand(TestBaseCommand): fake_lrouter = fakes.FakeOvsdbRow.create_one_ovsdb_row( attrs={'static_routes': [fake_route_1, fake_route_2], 'nat': []}) + self.ovn_api.get_lrouter_gw_ports.return_value = [] with mock.patch.object(self.ovn_api, "is_col_present", return_value=True): with mock.patch.object(idlutils, 'row_by_value', @@ -1234,6 +1235,7 @@ class TestDeleteLRouterExtGwCommand(TestBaseCommand): fake_lrouter = fakes.FakeOvsdbRow.create_one_ovsdb_row( attrs={'nat': [fake_nat_1, fake_nat_2], 'static_routes': []}) + self.ovn_api.get_lrouter_gw_ports.return_value = [] with mock.patch.object(self.ovn_api, "is_col_present", return_value=True): with mock.patch.object(idlutils, 'row_by_value', @@ -1246,10 +1248,11 @@ class TestDeleteLRouterExtGwCommand(TestBaseCommand): def test_delete_lrouter_extgw_ports(self): port_id = 'fake-port-id' + fake_lrp = fakes.FakeOvsdbRow.create_one_ovsdb_row( + attrs={'gateway_chassis': ['fake_gwc']}) fake_lrouter = fakes.FakeOvsdbRow.create_one_ovsdb_row( - attrs={'external_ids': - {ovn_const.OVN_GW_PORT_EXT_ID_KEY: port_id}, - 'static_routes': [], 'nat': []}) + attrs={'ports': [fake_lrp], 'static_routes': [], 'nat': []}) + self.ovn_api.get_lrouter_gw_ports.return_value = [fake_lrp] with mock.patch.object(self.ovn_api, "is_col_present", return_value=True): with mock.patch.object(idlutils, 'row_by_value', @@ -1258,22 +1261,21 @@ class TestDeleteLRouterExtGwCommand(TestBaseCommand): self.ovn_api, fake_lrouter.name, False) cmd.run_idl(self.transaction) fake_lrouter.delvalue.assert_called_once_with( - 'ports', port_id) + 'ports', fake_lrp) def test_delete_lrouter_extgw_ports_not_found(self): - port_id = 'fake-port-id' fake_lrouter = fakes.FakeOvsdbRow.create_one_ovsdb_row( - attrs={'external_ids': - {ovn_const.OVN_GW_PORT_EXT_ID_KEY: port_id}, - 'static_routes': [], 'nat': []}) + attrs={'static_routes': [], 'nat': []}) + self.ovn_api.get_lrouter_gw_ports.return_value = [] with mock.patch.object(self.ovn_api, "is_col_present", return_value=True): with mock.patch.object(idlutils, 'row_by_value', - side_effect=[fake_lrouter, - idlutils.RowNotFound]): + side_effect=[fake_lrouter]): cmd = commands.DeleteLRouterExtGwCommand( self.ovn_api, fake_lrouter.name, False) cmd.run_idl(self.transaction) + self.ovn_api.get_lrouter_gw_ports.assert_called_once_with( + fake_lrouter.name) fake_lrouter.delvalue.assert_not_called() def _test_delete_lrouter_no_lrouter_exist(self, if_exists=True): diff --git a/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_impl_idl_ovn.py b/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_impl_idl_ovn.py index 209a41bf98..2854672389 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_impl_idl_ovn.py +++ b/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_impl_idl_ovn.py @@ -161,7 +161,10 @@ class TestNBImplIdlOvn(TestDBImplIdlOvn): 'lr-name-d'}}, {'name': utils.ovn_name('lr-id-e'), 'external_ids': {ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: - 'lr-name-e'}}], + 'lr-name-e'}}, + {'name': utils.ovn_name('lr-id-f'), + 'external_ids': {ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: + 'lr-name-f'}}], 'lrouter_ports': [ {'name': utils.ovn_lrouter_port_name('orp-id-a1'), 'external_ids': {ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: @@ -169,10 +172,14 @@ class TestNBImplIdlOvn(TestDBImplIdlOvn): 'networks': ['10.0.1.0/24'], 'options': {ovn_const.OVN_GATEWAY_CHASSIS_KEY: 'host-1'}}, {'name': utils.ovn_lrouter_port_name('orp-id-a2'), - 'external_ids': {}, 'networks': ['10.0.2.0/24'], + 'external_ids': {ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: + 'lr-id-a'}, + 'networks': ['10.0.2.0/24'], 'options': {ovn_const.OVN_GATEWAY_CHASSIS_KEY: 'host-1'}}, {'name': utils.ovn_lrouter_port_name('orp-id-a3'), - 'external_ids': {}, 'networks': ['10.0.3.0/24'], + 'external_ids': {ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: + 'lr-id-a'}, + 'networks': ['10.0.3.0/24'], 'options': {ovn_const.OVN_GATEWAY_CHASSIS_KEY: ovn_const.OVN_GATEWAY_INVALID_CHASSIS}}, {'name': 'xrp-id-b1', @@ -182,7 +189,15 @@ class TestNBImplIdlOvn(TestDBImplIdlOvn): 'options': {ovn_const.OVN_GATEWAY_CHASSIS_KEY: 'host-2'}}, {'name': utils.ovn_lrouter_port_name('orp-id-b3'), 'external_ids': {}, 'networks': ['20.0.3.0/24'], + 'options': {}}, + {'name': utils.ovn_lrouter_port_name('gwc'), + 'external_ids': {ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: + 'lr-id-f'}, + 'networks': ['10.0.4.0/24'], 'options': {}}], + 'gateway_chassis': [ + {'chassis_name': 'fake-chassis', + 'name': utils.ovn_lrouter_port_name('gwc') + '_fake-chassis'}], 'static_routes': [{'ip_prefix': '20.0.0.0/16', 'nexthop': '10.0.3.253'}, {'ip_prefix': '10.0.0.0/16', @@ -317,7 +332,12 @@ class TestNBImplIdlOvn(TestDBImplIdlOvn): utils.ovn_lrouter_port_name('orp-id-a3')], utils.ovn_name('lr-id-b'): [ 'xrp-id-b1', - utils.ovn_lrouter_port_name('orp-id-b2')]}, + utils.ovn_lrouter_port_name('orp-id-b2')], + utils.ovn_name('lr-id-f'): [ + utils.ovn_lrouter_port_name('gwc')]}, + 'lrptogwc': { + utils.ovn_lrouter_port_name('gwc'): [ + utils.ovn_lrouter_port_name('gwc') + '_fake-chassis']}, 'lrtosroute': { utils.ovn_name('lr-id-a'): ['20.0.0.0/16'], utils.ovn_name('lr-id-b'): ['10.0.0.0/16'] @@ -346,6 +366,7 @@ class TestNBImplIdlOvn(TestDBImplIdlOvn): self.dhcp_table = fakes.FakeOvsdbTable.create_one_ovsdb_table() self.address_set_table = fakes.FakeOvsdbTable.create_one_ovsdb_table() self.lb_table = fakes.FakeOvsdbTable.create_one_ovsdb_table() + self.gwc_table = fakes.FakeOvsdbTable.create_one_ovsdb_table() self._tables = {} self._tables['Logical_Switch'] = self.lswitch_table @@ -358,6 +379,7 @@ class TestNBImplIdlOvn(TestDBImplIdlOvn): self._tables['Address_Set'] = self.address_set_table self._tables['Load_Balancer'] = self.lb_table self._tables['NAT'] = self.nat_table + self._tables['Gateway_Chassis'] = self.gwc_table with mock.patch.object(impl_idl_ovn.OvsdbNbOvnIdl, 'from_worker', return_value=mock.Mock()): @@ -379,16 +401,23 @@ class TestNBImplIdlOvn(TestDBImplIdlOvn): TestNBImplIdlOvn.fake_associations['lstolsp'], self.lswitch_table, self.lsp_table, 'name', 'name', 'ports') - # Load Routers and Router Ports + # Load Routers, Router Ports and Gateway Chassis fake_lrouters = TestNBImplIdlOvn.fake_set['lrouters'] self._load_ovsdb_fake_rows(self.lrouter_table, fake_lrouters) fake_lrps = TestNBImplIdlOvn.fake_set['lrouter_ports'] self._load_ovsdb_fake_rows(self.lrp_table, fake_lrps) + fake_gwc = TestNBImplIdlOvn.fake_set['gateway_chassis'] + self._load_ovsdb_fake_rows(self.gwc_table, fake_gwc) # Associate routers and router ports self._construct_ovsdb_references( TestNBImplIdlOvn.fake_associations['lrtolrp'], self.lrouter_table, self.lrp_table, 'name', 'name', 'ports') + # Associate router ports and gateway chassis + self._construct_ovsdb_references( + TestNBImplIdlOvn.fake_associations['lrptogwc'], + self.lrp_table, self.gwc_table, + 'name', 'name', 'gateway_chassis') # Load static routes fake_sroutes = TestNBImplIdlOvn.fake_set['static_routes'] self._load_ovsdb_fake_rows(self.sroute_table, fake_sroutes) @@ -484,6 +513,9 @@ class TestNBImplIdlOvn(TestDBImplIdlOvn): {'name': 'lr-id-d', 'ports': {}, 'static_routes': [], 'snats': [], 'dnat_and_snats': []}, {'name': 'lr-id-e', 'ports': {}, 'static_routes': [], + 'snats': [], 'dnat_and_snats': []}, + {'name': 'lr-id-f', 'static_routes': [], + 'ports': {'gwc': ['10.0.4.0/24']}, 'snats': [], 'dnat_and_snats': []}] self.assertCountEqual(mapping, expected) @@ -556,6 +588,11 @@ class TestNBImplIdlOvn(TestDBImplIdlOvn): def test_get_all_chassis_gateway_bindings(self): self._load_nb_db() + + # NOTE(fnordahl): The `Gateway_Chassis` table being present without + # proper associations fools the test, remove for now. + del(self._tables['Gateway_Chassis']) + bindings = self.nb_ovn_idl.get_all_chassis_gateway_bindings() expected = {'host-1': [utils.ovn_lrouter_port_name('orp-id-a1'), utils.ovn_lrouter_port_name('orp-id-a2')], @@ -574,6 +611,11 @@ class TestNBImplIdlOvn(TestDBImplIdlOvn): def test_get_gateway_chassis_binding(self): self._load_nb_db() + + # NOTE(fnordahl): The `Gateway_Chassis` table being present without + # proper associations fools the test, remove for now. + del(self._tables['Gateway_Chassis']) + chassis = self.nb_ovn_idl.get_gateway_chassis_binding( utils.ovn_lrouter_port_name('orp-id-a1')) self.assertEqual(chassis, ['host-1']) @@ -591,6 +633,11 @@ class TestNBImplIdlOvn(TestDBImplIdlOvn): def test_get_unhosted_gateways(self): self._load_nb_db() + + # NOTE(fnordahl): The `Gateway_Chassis` table being present without + # proper associations fools the test, remove for now. + del(self._tables['Gateway_Chassis']) + # Port physnet-dict port_physnet_dict = { 'orp-id-a1': 'physnet1', # scheduled @@ -626,6 +673,11 @@ class TestNBImplIdlOvn(TestDBImplIdlOvn): def test_get_unhosted_gateways_deleted_physnet(self): self._load_nb_db() + + # NOTE(fnordahl): The `Gateway_Chassis` table being present without + # proper associations fools the test, remove for now. + del(self._tables['Gateway_Chassis']) + # The LRP is on host-2 now router_row = self._find_ovsdb_fake_row(self.lrp_table, 'name', 'lrp-orp-id-a1') @@ -813,6 +865,29 @@ class TestNBImplIdlOvn(TestDBImplIdlOvn): lb = self.nb_ovn_idl.get_floatingip_in_nat_or_lb(fip_id) self.assertEqual(lb['_uuid'], lb_row.uuid) + def test_get_lrouter_gw_ports_legacy_option(self): + self._load_nb_db() + + gw1_row = self._find_ovsdb_fake_row( + self.lrp_table, 'name', utils.ovn_lrouter_port_name('orp-id-a1')) + gw2_row = self._find_ovsdb_fake_row( + self.lrp_table, 'name', utils.ovn_lrouter_port_name('orp-id-a2')) + gw3_row = self._find_ovsdb_fake_row( + self.lrp_table, 'name', utils.ovn_lrouter_port_name('orp-id-a3')) + + gw_ports = self.nb_ovn_idl.get_lrouter_gw_ports( + utils.ovn_name('lr-id-a')) + self.assertEqual([gw1_row, gw2_row, gw3_row], gw_ports) + + def test_get_lrouter_gw_ports_gwc(self): + self._load_nb_db() + gw1_row = self._find_ovsdb_fake_row( + self.lrp_table, 'name', utils.ovn_lrouter_port_name('gwc')) + + gw_ports = self.nb_ovn_idl.get_lrouter_gw_ports( + utils.ovn_name('lr-id-f')) + self.assertEqual([gw1_row], gw_ports) + class TestSBImplIdlOvnBase(TestDBImplIdlOvn): diff --git a/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_maintenance.py b/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_maintenance.py index b22e0a5470..e05f324deb 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_maintenance.py +++ b/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_maintenance.py @@ -586,6 +586,102 @@ class TestDBInconsistenciesPeriodics(testlib_api.SqlTestCaseLight, nb_idl.lsp_set_options.assert_has_calls(expected_calls) + def test_check_localnet_port_has_learn_fdb(self): + cfg.CONF.set_override('localnet_learn_fdb', 'True', + group='ovn') + nb_idl = self.fake_ovn_client._nb_idl + + # Already has the learn fdb option enabled + lsp0 = fakes.FakeOvsdbRow.create_one_ovsdb_row( + attrs={ + "name": "lsp0", + "options": { + constants.LSP_OPTIONS_LOCALNET_LEARN_FDB: "true", + }, + } + ) + + # learn fdb option missing, needs update + lsp1 = fakes.FakeOvsdbRow.create_one_ovsdb_row( + attrs={ + "name": "lsp1", + "options": {}, + } + ) + + # learn fdb option set to false, needs update + lsp2 = fakes.FakeOvsdbRow.create_one_ovsdb_row( + attrs={ + "name": "lsp2", + "options": { + constants.LSP_OPTIONS_LOCALNET_LEARN_FDB: "false", + }, + } + ) + + nb_idl.db_find_rows.return_value.execute.return_value = [ + lsp0, + lsp1, + lsp2, + ] + + self.assertRaises( + periodics.NeverAgain, + self.periodic.check_localnet_port_has_learn_fdb) + + options = {constants.LSP_OPTIONS_LOCALNET_LEARN_FDB: 'true'} + expected_calls = [mock.call('Logical_Switch_Port', 'lsp1', + ('options', options)), + mock.call('Logical_Switch_Port', 'lsp2', + ('options', options))] + nb_idl.db_set.assert_has_calls(expected_calls) + + def test_check_localnet_port_has_learn_fdb_disabled(self): + nb_idl = self.fake_ovn_client._nb_idl + + # learn fdb option enabled, needs update + lsp0 = fakes.FakeOvsdbRow.create_one_ovsdb_row( + attrs={ + "name": "lsp0", + "options": { + constants.LSP_OPTIONS_LOCALNET_LEARN_FDB: "true", + }, + } + ) + + # learn fdb option missing, no update needed + lsp1 = fakes.FakeOvsdbRow.create_one_ovsdb_row( + attrs={ + "name": "lsp1", + "options": {}, + } + ) + + # learn fdb option set to false, no update needed + lsp2 = fakes.FakeOvsdbRow.create_one_ovsdb_row( + attrs={ + "name": "lsp2", + "options": { + constants.LSP_OPTIONS_LOCALNET_LEARN_FDB: "false", + }, + } + ) + + nb_idl.db_find_rows.return_value.execute.return_value = [ + lsp0, + lsp1, + lsp2, + ] + + self.assertRaises( + periodics.NeverAgain, + self.periodic.check_localnet_port_has_learn_fdb) + + options = {constants.LSP_OPTIONS_LOCALNET_LEARN_FDB: 'false'} + expected_calls = [mock.call('Logical_Switch_Port', 'lsp0', + ('options', options))] + nb_idl.db_set.assert_has_calls(expected_calls) + def test_check_router_mac_binding_options(self): nb_idl = self.fake_ovn_client._nb_idl lr0 = fakes.FakeOvsdbRow.create_one_ovsdb_row( @@ -716,18 +812,18 @@ class TestDBInconsistenciesPeriodics(testlib_api.SqlTestCaseLight, self.fake_ovn_client._nb_idl.db_set.assert_has_calls( expected_calls) - def test_update_logical_router_with_gateway_network_id(self): + def test_remove_gw_ext_ids_from_logical_router(self): nb_idl = self.fake_ovn_client._nb_idl - # lr0: GW port ID, not GW network ID --> we need to add network ID. + # lr0: GW port ID, not GW network ID --> we need to remove port ID. lr0 = fakes.FakeOvsdbRow.create_one_ovsdb_row(attrs={ 'name': 'lr0', 'external_ids': {constants.OVN_GW_PORT_EXT_ID_KEY: 'port0'}}) - # lr1: GW port ID and not GW network ID --> register already updated. + # lr1: GW port ID and GW network ID --> we need to remove both. lr1 = fakes.FakeOvsdbRow.create_one_ovsdb_row(attrs={ 'name': 'lr1', 'external_ids': {constants.OVN_GW_PORT_EXT_ID_KEY: 'port1', constants.OVN_GW_NETWORK_EXT_ID_KEY: 'net1'}}) - # lr2: no GW port ID (nor GW network ID) --> no QoS. + # lr2: no GW port ID (nor GW network ID) --> no action needed. lr2 = fakes.FakeOvsdbRow.create_one_ovsdb_row(attrs={ 'name': 'lr2', 'external_ids': {}}) nb_idl.lr_list.return_value.execute.return_value = (lr0, lr1, lr2) @@ -736,10 +832,11 @@ class TestDBInconsistenciesPeriodics(testlib_api.SqlTestCaseLight, self.assertRaises( periodics.NeverAgain, - self.periodic.update_logical_router_with_gateway_network_id) - ext_ids = {constants.OVN_GW_NETWORK_EXT_ID_KEY: 'net0'} + self.periodic.remove_gw_ext_ids_from_logical_router) expected_calls = [mock.call('Logical_Router', lr0.uuid, - ('external_ids', ext_ids))] + ('external_ids', {})), + mock.call('Logical_Router', lr1.uuid, + ('external_ids', {}))] nb_idl.db_set.assert_has_calls(expected_calls) def _test_check_baremetal_ports_dhcp_options(self, dhcp_disabled=False): diff --git a/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_client.py b/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_client.py index 9e6adb8bc9..d0f2eb599f 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_client.py +++ b/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_client.py @@ -21,9 +21,12 @@ from neutron.conf.plugins.ml2.drivers.ovn import ovn_conf from neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb import ovn_client from neutron.tests import base from neutron.tests.unit import fake_resources as fakes +from neutron.tests.unit.services.logapi.drivers.ovn \ + import test_driver as test_log_driver from neutron_lib.api.definitions import l3 from neutron_lib.api.definitions import portbindings from neutron_lib import constants as const +from neutron_lib.services.logapi import constants as log_const class TestOVNClientBase(base.BaseTestCase): @@ -191,3 +194,61 @@ class TestOVNClientDetermineBindHost(TestOVNClientBase): self.assertEqual( self.fake_smartnic_hostname, self.ovn_client.determine_bind_host({}, port_context=context)) + + +class TestOVNClientFairMeter(TestOVNClientBase, + test_log_driver.TestOVNDriverBase): + + def test_create_ovn_fair_meter(self): + mock_find_rows = mock.Mock() + mock_find_rows.execute.return_value = None + self.nb_idl.db_find_rows.return_value = mock_find_rows + self.ovn_client.create_ovn_fair_meter(self._log_driver.meter_name) + self.assertFalse(self.nb_idl.meter_del.called) + self.assertTrue(self.nb_idl.meter_add.called) + self.nb_idl.meter_add.assert_called_once_with( + name=self._log_driver.meter_name, + unit="pktps", + rate=self.fake_cfg_network_log.rate_limit, + fair=True, + burst_size=self.fake_cfg_network_log.burst_limit, + may_exist=False, + external_ids={constants.OVN_DEVICE_OWNER_EXT_ID_KEY: + log_const.LOGGING_PLUGIN}) + + def test_create_ovn_fair_meter_unchanged(self): + mock_find_rows = mock.Mock() + mock_find_rows.execute.return_value = [self._fake_meter()] + self.nb_idl.db_find_rows.return_value = mock_find_rows + self.nb_idl.lookup.side_effect = lambda table, key, default: ( + self._fake_meter_band() if key == "test_band" else default) + self.ovn_client.create_ovn_fair_meter(self._log_driver.meter_name) + self.assertFalse(self.nb_idl.meter_del.called) + self.assertFalse(self.nb_idl.meter_add.called) + + def test_create_ovn_fair_meter_changed(self): + mock_find_rows = mock.Mock() + mock_find_rows.execute.return_value = [self._fake_meter(fair=[False])] + self.nb_idl.db_find_rows.return_value = mock_find_rows + self.nb_idl.lookup.return_value = self._fake_meter_band() + self.ovn_client.create_ovn_fair_meter(self._log_driver.meter_name) + self.assertTrue(self.nb_idl.meter_del.called) + self.assertTrue(self.nb_idl.meter_add.called) + + def test_create_ovn_fair_meter_band_changed(self): + mock_find_rows = mock.Mock() + mock_find_rows.execute.return_value = [self._fake_meter()] + self.nb_idl.db_find_rows.return_value = mock_find_rows + self.nb_idl.lookup.return_value = self._fake_meter_band(rate=666) + self.ovn_client.create_ovn_fair_meter(self._log_driver.meter_name) + self.assertTrue(self.nb_idl.meter_del.called) + self.assertTrue(self.nb_idl.meter_add.called) + + def test_create_ovn_fair_meter_band_missing(self): + mock_find_rows = mock.Mock() + mock_find_rows.execute.return_value = [self._fake_meter()] + self.nb_idl.db_find_rows.return_value = mock_find_rows + self.nb_idl.lookup.side_effect = None + self.ovn_client.create_ovn_fair_meter(self._log_driver.meter_name) + self.assertTrue(self.nb_idl.meter_del.called) + self.assertTrue(self.nb_idl.meter_add.called) diff --git a/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py b/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py index f768bf7635..fb8a747919 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py +++ b/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py @@ -34,6 +34,7 @@ from neutron_lib import context from neutron_lib import exceptions as n_exc from neutron_lib.placement import utils as place_utils from neutron_lib.plugins import directory +from neutron_lib.plugins import utils as p_utils from neutron_lib.tests import tools from neutron_lib.utils import net as n_net from oslo_concurrency import processutils @@ -448,11 +449,10 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): {'vtep-physical-switch': 'psw1', 'vtep-logical-switch': 'lsw1', 'tag': 1024, 'parent_name': 'fakename'}, ] - with self.network(set_context=True, tenant_id='test') as net1: + with self.network() as net1: with self.subnet(network=net1) as subnet1: # succeed without binding:profile - with self.port(subnet=subnet1, - set_context=True, tenant_id='test'): + with self.port(subnet=subnet1): pass # fail with invalid binding profiles for invalid_profile in invalid_binding_profiles: @@ -464,7 +464,6 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): expected_res_status=403, arg_list=( ovn_const.OVN_PORT_BINDING_PROFILE,), - set_context=True, tenant_id='test', **kwargs): pass except exc.HTTPClientError: @@ -533,10 +532,9 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): 'opt_value': 'apple'}, {'ip_version': 6, 'opt_name': 'grape', 'opt_value': 'grape'}]}} - with self.network(set_context=True, tenant_id='test') as net: + with self.network() as net: with self.subnet(network=net) as subnet: - with self.port(subnet=subnet, - set_context=True, tenant_id='test') as port: + with self.port(subnet=subnet) as port: port_id = port['port']['id'] self._update('ports', port_id, data) @@ -547,11 +545,12 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): mock_log.assert_has_calls([expected_call]) def test_create_and_update_ignored_fip_port(self): - with self.network(set_context=True, tenant_id='test') as net1: + with self.network() as net1: with self.subnet(network=net1) as subnet1: - with self.port(subnet=subnet1, - device_owner=const.DEVICE_OWNER_FLOATINGIP, - set_context=True, tenant_id='test') as port: + with self.port( + subnet=subnet1, + is_admin=True, + device_owner=const.DEVICE_OWNER_FLOATINGIP) as port: self.nb_ovn.create_lswitch_port.assert_not_called() data = {'port': {'name': 'new'}} req = self.new_update_request('ports', data, @@ -561,15 +560,17 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): self.nb_ovn.set_lswitch_port.assert_not_called() def test_update_ignored_port_from_fip_device_owner(self): - with self.network(set_context=True, tenant_id='test') as net1: + with self.network() as net1: with self.subnet(network=net1) as subnet1: - with self.port(subnet=subnet1, - device_owner=const.DEVICE_OWNER_FLOATINGIP, - set_context=True, tenant_id='test') as port: + with self.port( + subnet=subnet1, + is_admin=True, + device_owner=const.DEVICE_OWNER_FLOATINGIP) as port: self.nb_ovn.create_lswitch_port.assert_not_called() data = {'port': {'device_owner': 'test'}} req = self.new_update_request('ports', data, - port['port']['id']) + port['port']['id'], + as_admin=True) res = req.get_response(self.api) self.assertEqual(exc.HTTPBadRequest.code, res.status_int) msg = jsonutils.loads(res.body)['NeutronError']['message'] @@ -580,17 +581,18 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): self.nb_ovn.set_lswitch_port.assert_not_called() def test_update_ignored_port_to_fip_device_owner(self): - with self.network(set_context=True, tenant_id='test') as net1: + with self.network() as net1: with self.subnet(network=net1) as subnet1: with self.port(subnet=subnet1, - device_owner='test', - set_context=True, tenant_id='test') as port: + is_admin=True, + device_owner='test') as port: self.assertEqual( 1, self.nb_ovn.create_lswitch_port.call_count) data = {'port': {'device_owner': const.DEVICE_OWNER_FLOATINGIP}} req = self.new_update_request('ports', data, - port['port']['id']) + port['port']['id'], + as_admin=True) res = req.get_response(self.api) self.assertEqual(exc.HTTPBadRequest.code, res.status_int) msg = jsonutils.loads(res.body)['NeutronError']['message'] @@ -604,11 +606,11 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): kwargs = {'mac_address': '00:00:00:00:00:01', 'fixed_ips': [{'ip_address': '10.0.0.2'}, {'ip_address': '10.0.0.4'}]} - with self.network(set_context=True, tenant_id='test') as net1: + with self.network() as net1: with self.subnet(network=net1) as subnet1: with self.port(subnet=subnet1, + is_admin=True, arg_list=('mac_address', 'fixed_ips'), - set_context=True, tenant_id='test', **kwargs) as port: self.assertTrue(self.nb_ovn.create_lswitch_port.called) called_args_dict = ( @@ -620,7 +622,8 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): data = {'port': {'mac_address': '00:00:00:00:00:02'}} req = self.new_update_request( 'ports', - data, port['port']['id']) + data, port['port']['id'], + as_admin=True) req.get_response(self.api) self.assertTrue(self.nb_ovn.set_lswitch_port.called) called_args_dict = ( @@ -634,11 +637,10 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): # be treated as VIP. kwargs = {'port_security_enabled': False, 'device_owner': 'compute:nova'} - with self.network(set_context=True, tenant_id='test') as net1: + with self.network() as net1: with self.subnet(network=net1) as subnet1: with self.port(subnet=subnet1, arg_list=('port_security_enabled',), - set_context=True, tenant_id='test', **kwargs) as port: self.assertTrue(self.nb_ovn.create_lswitch_port.called) called_args_dict = ( @@ -652,7 +654,8 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): data = {'port': {'mac_address': '00:00:00:00:00:01'}} req = self.new_update_request( 'ports', - data, port['port']['id']) + data, port['port']['id'], + as_admin=True) req.get_response(self.api) self.assertTrue(self.nb_ovn.set_lswitch_port.called) called_args_dict = ( @@ -686,11 +689,11 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): {"ip_address": "2.2.2.2", "mac_address": "22:22:22:22:22:22"}], 'device_owner': 'compute:nova'} - with self.network(set_context=True, tenant_id='test') as net1: + with self.network() as net1: with self.subnet(network=net1) as subnet1: with self.port(subnet=subnet1, + is_admin=True, arg_list=('allowed_address_pairs',), - set_context=True, tenant_id='test', **kwargs) as port: port_ip = port['port'].get('fixed_ips')[0]['ip_address'] self.assertTrue(self.nb_ovn.create_lswitch_port.called) @@ -717,7 +720,8 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): data = {'port': {'mac_address': '00:00:00:00:00:01'}} req = self.new_update_request( 'ports', - data, port['port']['id']) + data, port['port']['id'], + as_admin=True) req.get_response(self.api) self.assertTrue(self.nb_ovn.set_lswitch_port.called) called_args_dict = ( @@ -736,10 +740,10 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): called_args_dict.get('addresses')) def test_create_port_ovn_octavia_vip(self): - with (self.network(set_context=True, tenant_id='test')) as net1, ( - self.subnet(network=net1)) as subnet1, ( + with self.network() as net1,\ + self.subnet(network=net1) as subnet1,\ self.port(name=ovn_const.LB_VIP_PORT_PREFIX + 'foo', - subnet=subnet1, set_context=True, tenant_id='test')): + subnet=subnet1): self.assertTrue(self.nb_ovn.create_lswitch_port.called) called_args_dict = ( @@ -864,6 +868,7 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): pnet.PHYSICAL_NETWORK: 'physnet1', pnet.SEGMENTATION_ID: '2'} net = self._make_network(self.fmt, 'net1', True, + as_admin=True, arg_list=(pnet.NETWORK_TYPE, pnet.PHYSICAL_NETWORK, pnet.SEGMENTATION_ID,), @@ -877,17 +882,17 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): lswitch_name=ovn_utils.ovn_name(net['id']), options={'network_name': 'physnet1', ovn_const.LSP_OPTIONS_MCAST_FLOOD_REPORTS: 'true', - ovn_const.LSP_OPTIONS_MCAST_FLOOD: 'false'}, + ovn_const.LSP_OPTIONS_MCAST_FLOOD: 'false', + ovn_const.LSP_OPTIONS_LOCALNET_LEARN_FDB: 'false'}, tag=2, type='localnet') def test_create_port_without_security_groups(self): kwargs = {'security_groups': []} - with self.network(set_context=True, tenant_id='test') as net1: + with self.network() as net1: with self.subnet(network=net1) as subnet1: with self.port(subnet=subnet1, arg_list=('security_groups',), - set_context=True, tenant_id='test', **kwargs): self.assertEqual( 1, self.nb_ovn.create_lswitch_port.call_count) @@ -895,22 +900,20 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): def test_create_port_without_security_groups_no_ps(self): kwargs = {'security_groups': [], 'port_security_enabled': False} - with self.network(set_context=True, tenant_id='test') as net1: + with self.network() as net1: with self.subnet(network=net1) as subnet1: with self.port(subnet=subnet1, arg_list=('security_groups', 'port_security_enabled'), - set_context=True, tenant_id='test', **kwargs): self.assertEqual( 1, self.nb_ovn.create_lswitch_port.call_count) self.nb_ovn.add_acl.assert_not_called() def test_update_port_changed_security_groups(self): - with self.network(set_context=True, tenant_id='test') as net1: + with self.network() as net1: with self.subnet(network=net1) as subnet1: - with self.port(subnet=subnet1, - set_context=True, tenant_id='test') as port1: + with self.port(subnet=subnet1) as port1: sg_id = port1['port']['security_groups'][0] fake_lsp = ( fakes.FakeOVNPort.from_neutron_port( @@ -937,10 +940,9 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): self.assertTrue(self.nb_ovn.pg_add_ports.called) def test_update_port_unchanged_security_groups(self): - with self.network(set_context=True, tenant_id='test') as net1: + with self.network() as net1: with self.subnet(network=net1) as subnet1: - with self.port(subnet=subnet1, - set_context=True, tenant_id='test') as port1: + with self.port(subnet=subnet1) as port1: fake_lsp = ( fakes.FakeOVNPort.from_neutron_port( port1['port'])) @@ -966,11 +968,9 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): def _test_update_port_vip(self, is_vip=True): kwargs = {} - with ( - self.network(set_context=True, tenant_id='test')) as net1, ( - self.subnet(network=net1)) as subnet1, ( - self.port(subnet=subnet1, set_context=True, - tenant_id='test', **kwargs)) as port1: + with self.network() as net1, \ + self.subnet(network=net1) as subnet1, \ + self.port(subnet=subnet1, **kwargs) as port1: fake_lsp = ( fakes.FakeOVNPort.from_neutron_port( port1['port'])) @@ -1000,11 +1000,10 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): def test_delete_port_without_security_groups(self): kwargs = {'security_groups': []} - with self.network(set_context=True, tenant_id='test') as net1: + with self.network() as net1: with self.subnet(network=net1) as subnet1: with self.port(subnet=subnet1, arg_list=('security_groups',), - set_context=True, tenant_id='test', **kwargs) as port1: fake_lsp = ( fakes.FakeOVNPort.from_neutron_port( @@ -1021,10 +1020,9 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): def test_delete_port_exception_delete_revision(self, mock_del_port, mock_del_rev): mock_del_port.side_effect = Exception('BoOoOoOoOmmmmm!!!') - with self.network(set_context=True, tenant_id='test') as net: + with self.network() as net: with self.subnet(network=net) as subnet: - with self.port(subnet=subnet, - set_context=True, tenant_id='test') as port: + with self.port(subnet=subnet) as port: self._delete('ports', port['port']['id']) # Assert that delete_revision wasn't invoked mock_del_rev.assert_not_called() @@ -1034,10 +1032,9 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): def test_delete_port_not_exist_in_ovn(self, mock_del_port, mock_del_rev): mock_del_port.side_effect = idlutils.RowNotFound - with self.network(set_context=True, tenant_id='test') as net: + with self.network() as net: with self.subnet(network=net) as subnet: - with self.port(subnet=subnet, - set_context=True, tenant_id='test') as port: + with self.port(subnet=subnet) as port: self._delete('ports', port['port']['id']) # Assert that delete_revision wasn't invoked mock_del_rev.assert_not_called() @@ -1049,14 +1046,13 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): created_at = timeutils.utcnow() - datetime.timedelta( seconds=ovn_const.DB_CONSISTENCY_CHECK_INTERVAL * 2) mock_del_port.side_effect = idlutils.RowNotFound - with self.network(set_context=True, tenant_id='test') as net: + with self.network() as net: with self.subnet(network=net) as subnet: - with self.port(subnet=subnet, - set_context=True, tenant_id='test') as port, \ - mock.patch.object(ovn_revision_numbers_db, - 'get_revision_row', - return_value=OvnRevNumberRow( - created_at=created_at)): + with self.port(subnet=subnet) as port, \ + mock.patch.object(ovn_revision_numbers_db, + 'get_revision_row', + return_value=OvnRevNumberRow( + created_at=created_at)): self._delete('ports', port['port']['id']) # Assert that delete_revision was invoked mock_del_rev.assert_called_once_with(mock.ANY, @@ -1066,10 +1062,9 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): def _test_set_port_status_up(self, is_compute_port=False): port_device_owner = 'compute:nova' if is_compute_port else '' self.mech_driver._plugin.nova_notifier = mock.Mock() - with self.network(set_context=True, tenant_id='test') as net1, \ + with self.network() as net1, \ self.subnet(network=net1) as subnet1, \ - self.port(subnet=subnet1, set_context=True, - tenant_id='test', + self.port(subnet=subnet1, is_admin=True, device_owner=port_device_owner) as port1, \ mock.patch.object(provisioning_blocks, 'provisioning_complete') as pc, \ @@ -1105,10 +1100,9 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): def _test_set_port_status_down(self, is_compute_port=False): port_device_owner = 'compute:nova' if is_compute_port else '' self.mech_driver._plugin.nova_notifier = mock.Mock() - with self.network(set_context=True, tenant_id='test') as net1, \ + with self.network() as net1, \ self.subnet(network=net1) as subnet1, \ - self.port(subnet=subnet1, set_context=True, - tenant_id='test', + self.port(subnet=subnet1, is_admin=True, device_owner=port_device_owner) as port1, \ mock.patch.object(provisioning_blocks, 'add_provisioning_component') as apc, \ @@ -1157,10 +1151,9 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): def test_set_port_status_concurrent_delete(self): exc = os_db_exc.DBReferenceError('', '', '', '') - with self.network(set_context=True, tenant_id='test') as net1, \ + with self.network() as net1, \ self.subnet(network=net1) as subnet1, \ - self.port(subnet=subnet1, set_context=True, - tenant_id='test') as port1, \ + self.port(subnet=subnet1) as port1, \ mock.patch.object(provisioning_blocks, 'add_provisioning_component', side_effect=exc) as apc, \ @@ -1250,6 +1243,28 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): portbindings.VIF_TYPE_OVS, self.mech_driver.vif_details[portbindings.VIF_TYPE_OVS]) + def _test_bind_port_virtio_forwarder(self, fake_segments): + fake_port = fakes.FakePort.create_one_port( + attrs={'binding:vnic_type': 'virtio-forwarder'}).info() + fake_host = 'host' + fake_port_context = fakes.FakePortContext( + fake_port, fake_host, fake_segments) + self.mech_driver.bind_port(fake_port_context) + + vif_details = self.mech_driver.\ + vif_details[portbindings.VIF_TYPE_AGILIO_OVS] + vif_details.update({"vhostuser_socket": ovn_utils.ovn_vhu_sockpath( + ovn_conf.get_ovn_vhost_sock_dir(), fake_port['id'])}) + vif_details.update({"vhostuser_mode": "client"}) + + neutron_agent.AgentCache().get_agents.assert_called_once_with( + {'host': fake_host, + 'agent_type': ovn_const.OVN_CONTROLLER_TYPES}) + fake_port_context.set_binding.assert_called_once_with( + fake_segments[0]['id'], + portbindings.VIF_TYPE_AGILIO_OVS, + vif_details) + def _test_bind_port_remote_managed(self, fake_segments): fake_serial = 'fake-serial' fake_port = fakes.FakePort.create_one_port( @@ -1329,6 +1344,15 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): [fakes.FakeSegment.create_one_segment(attrs=segment_attrs).info()] self._test_bind_port_remote_managed(fake_segments) + def test_bind_virtio_forwarder_port_geneve(self): + """Test binding a VIRTIO_FORWARDER port to a geneve segment.""" + segment_attrs = {'network_type': 'geneve', + 'physical_network': None, + 'segmentation_id': 1023} + fake_segments = \ + [fakes.FakeSegment.create_one_segment(attrs=segment_attrs).info()] + self._test_bind_port_virtio_forwarder(fake_segments) + def test_bind_remote_managed_port_vlan(self): """Test binding a REMOTE_MANAGED port to a geneve segment.""" segment_attrs = {'network_type': 'vlan', @@ -1362,6 +1386,15 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): [fakes.FakeSegment.create_one_segment(attrs=segment_attrs).info()] self._test_bind_port(fake_segments) + def test_bind_virtio_forwarder_port_vxlan(self): + """Test binding a VIRTIO_FORWARDER port to a vxlan segment.""" + segment_attrs = {'network_type': 'vxlan', + 'physical_network': None, + 'segmentation_id': 1024} + fake_segments = \ + [fakes.FakeSegment.create_one_segment(attrs=segment_attrs).info()] + self._test_bind_port_virtio_forwarder(fake_segments) + def test__is_port_provisioning_required(self): fake_port = fakes.FakePort.create_one_port( attrs={'binding:vnic_type': 'normal', @@ -1754,7 +1787,8 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): self.mech_driver.update_subnet_postcommit(context) esd.assert_called_once_with( context.current, context.network.current, mock.ANY) - umd.assert_called_once_with(mock.ANY, 'id', subnet=subnet) + umd.assert_called_once_with(mock.ANY, context.network.current, + subnet=subnet) def test_update_subnet_postcommit_disable_dhcp(self): self.mech_driver.nb_ovn.get_subnet_dhcp_options.return_value = { @@ -1770,7 +1804,8 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): 'update_metadata_port') as umd: self.mech_driver.update_subnet_postcommit(context) dsd.assert_called_once_with(context.current['id'], mock.ANY) - umd.assert_called_once_with(mock.ANY, 'id', subnet=subnet) + umd.assert_called_once_with(mock.ANY, context.network.current, + subnet=subnet) def test_update_subnet_postcommit_update_dhcp(self): self.mech_driver.nb_ovn.get_subnet_dhcp_options.return_value = { @@ -1787,7 +1822,8 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): self.mech_driver.update_subnet_postcommit(context) usd.assert_called_once_with( context.current, context.network.current, mock.ANY) - umd.assert_called_once_with(mock.ANY, 'id', subnet=subnet) + umd.assert_called_once_with(mock.ANY, context.network.current, + subnet=subnet) def test__get_port_options(self): with mock.patch.object(self.mech_driver._plugin, 'get_subnets') as \ @@ -1979,9 +2015,10 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): mock_metaport.return_value = {'fixed_ips': fixed_ips, 'id': 'metadata_id'} mock_get_subnets.return_value = [{'id': 'subnet1'}] + network = {'id': 'net_id'} subnet = {'id': 'subnet1', 'enable_dhcp': True} self.mech_driver._ovn_client.update_metadata_port( - self.context, 'net_id', subnet=subnet) + self.context, network, subnet=subnet) mock_update_port.assert_not_called() # Subnet without DHCP, present in port. @@ -1991,7 +2028,7 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): mock_get_subnets.return_value = [{'id': 'subnet1'}] subnet = {'id': 'subnet1', 'enable_dhcp': False} self.mech_driver._ovn_client.update_metadata_port( - self.context, 'net_id', subnet=subnet) + self.context, network, subnet=subnet) port = {'id': 'metadata_id', 'port': {'network_id': 'net_id', 'fixed_ips': []}} mock_update_port.assert_called_once_with(mock.ANY, 'metadata_id', @@ -2004,7 +2041,7 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): mock_get_subnets.return_value = [] subnet = {'id': 'subnet1', 'enable_dhcp': True} self.mech_driver._ovn_client.update_metadata_port( - self.context, 'net_id', subnet=subnet) + self.context, network, subnet=subnet) fixed_ips = [{'subnet_id': 'subnet1'}] port = {'id': 'metadata_id', 'port': {'network_id': 'net_id', 'fixed_ips': fixed_ips}} @@ -2018,7 +2055,7 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): mock_get_subnets.return_value = [] subnet = {'id': 'subnet1', 'enable_dhcp': False} self.mech_driver._ovn_client.update_metadata_port( - self.context, 'net_id', subnet=subnet) + self.context, network, subnet=subnet) mock_update_port.assert_not_called() def test_update_metadata_port_no_subnet(self): @@ -2035,10 +2072,11 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): mock_get_subnets.return_value = [{'id': 'subnet1'}, {'id': 'subnet2'}] fixed_ips = [{'subnet_id': 'subnet1', 'ip_address': 'ip_add1'}] + network = {'id': 'net_id'} mock_metaport.return_value = {'fixed_ips': fixed_ips, 'id': 'metadata_id'} self.mech_driver._ovn_client.update_metadata_port(self.context, - 'net_id') + network) port = {'id': 'metadata_id', 'port': {'network_id': 'net_id', 'fixed_ips': fixed_ips}} fixed_ips.append({'subnet_id': 'subnet2'}) @@ -2049,10 +2087,11 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): # Port with IP in subnet1; subnet1 with DHCP, subnet2 without DHCP. mock_get_subnets.return_value = [{'id': 'subnet1'}] fixed_ips = [{'subnet_id': 'subnet1', 'ip_address': 'ip_add1'}] + network = {'id': 'net_id'} mock_metaport.return_value = {'fixed_ips': fixed_ips, 'id': 'metadata_id'} self.mech_driver._ovn_client.update_metadata_port(self.context, - 'net_id') + network) mock_update_port.assert_not_called() # Port with IP in subnet1; subnet1 without DHCP. @@ -2061,13 +2100,51 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): mock_metaport.return_value = {'fixed_ips': fixed_ips, 'id': 'metadata_id'} self.mech_driver._ovn_client.update_metadata_port(self.context, - 'net_id') + network) port = {'id': 'metadata_id', 'port': {'network_id': 'net_id', 'fixed_ips': []}} mock_update_port.assert_called_once_with( mock.ANY, 'metadata_id', port) mock_update_port.reset_mock() + def test_update_metadata_port_no_port(self): + ovn_conf.cfg.CONF.set_override('ovn_metadata_enabled', True, + group='ovn') + + with mock.patch.object( + self.mech_driver._ovn_client, '_find_metadata_port') as \ + mock_find_metaport, \ + mock.patch.object(self.mech_driver._plugin, 'get_subnets') as \ + mock_get_subnets, \ + mock.patch.object(p_utils, 'create_port') as \ + mock_create_port: + # Subnet with DHCP, no port, port created. + network = {'id': 'net_id', 'project_id': 'project_id-foo'} + subnet = {'id': 'subnet1', 'enable_dhcp': True} + fixed_ips = [{'subnet_id': 'subnet1', 'ip_address': 'ip_add1'}] + port = {'id': 'metadata_id', + 'network_id': 'net_id', + 'device_owner': const.DEVICE_OWNER_DISTRIBUTED, + 'device_id': 'ovnmeta-%s' % 'net_id', + 'fixed_ips': fixed_ips} + mock_get_subnets.return_value = [subnet] + mock_find_metaport.return_value = None + + # Subnet with DHCP, no port, port create failure. + mock_create_port.return_value = None + ret_status = self.mech_driver._ovn_client.update_metadata_port( + self.context, network, subnet=subnet) + self.assertFalse(ret_status) + mock_create_port.assert_called_once() + + # Subnet with DHCP, no port, port created successfully. + mock_create_port.reset_mock() + mock_create_port.return_value = port + ret_status = self.mech_driver._ovn_client.update_metadata_port( + self.context, network, subnet=subnet) + self.assertTrue(ret_status) + mock_create_port.assert_called_once() + @mock.patch.object(provisioning_blocks, 'is_object_blocked') @mock.patch.object(provisioning_blocks, 'provisioning_complete') def test_notify_dhcp_updated(self, mock_prov_complete, mock_is_obj_block): @@ -2366,7 +2443,8 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): def _test_update_network_fragmentation(self, new_mtu, expected_opts, grps): network_attrs = {external_net.EXTERNAL: True} network = self._make_network( - self.fmt, 'net1', True, arg_list=(external_net.EXTERNAL,), + self.fmt, 'net1', True, as_admin=True, + arg_list=(external_net.EXTERNAL,), **network_attrs) with self.subnet(network=network) as subnet: @@ -2667,6 +2745,7 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): pnet.PHYSICAL_NETWORK: 'physnet1', pnet.SEGMENTATION_ID: '1'} net = self._make_network(self.fmt, 'net1', True, + as_admin=True, arg_list=(pnet.NETWORK_TYPE, pnet.PHYSICAL_NETWORK, pnet.SEGMENTATION_ID,), @@ -2679,7 +2758,8 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase): # Issue an update to the network changing the segmentation_id data = {'network': {pnet.SEGMENTATION_ID: new_vlan_tag}} - req = self.new_update_request('networks', data, net['id']) + req = self.new_update_request('networks', data, net['id'], + as_admin=True) res = self.deserialize(self.fmt, req.get_response(self.api)) self.assertEqual(new_vlan_tag, res['network'][pnet.SEGMENTATION_ID]) @@ -2809,6 +2889,7 @@ class TestOVNMechanismDriverSubnetsV2(test_plugin.TestMl2SubnetsV2, net_arg = {pnet.NETWORK_TYPE: 'geneve', pnet.SEGMENTATION_ID: '1'} network = self._make_network(self.fmt, 'net1', True, + as_admin=True, arg_list=(pnet.NETWORK_TYPE, pnet.SEGMENTATION_ID,), **net_arg) @@ -2949,7 +3030,8 @@ class TestOVNMechanismDriverSegment(MechDriverSetupBase, lswitch_name=ovn_utils.ovn_name(net['id']), options={'network_name': 'physnet1', ovn_const.LSP_OPTIONS_MCAST_FLOOD_REPORTS: 'true', - ovn_const.LSP_OPTIONS_MCAST_FLOOD: 'false'}, + ovn_const.LSP_OPTIONS_MCAST_FLOOD: 'false', + ovn_const.LSP_OPTIONS_LOCALNET_LEARN_FDB: 'false'}, tag=200, type='localnet') ovn_nb_api.create_lswitch_port.reset_mock() @@ -2963,7 +3045,8 @@ class TestOVNMechanismDriverSegment(MechDriverSetupBase, lswitch_name=ovn_utils.ovn_name(net['id']), options={'network_name': 'physnet2', ovn_const.LSP_OPTIONS_MCAST_FLOOD_REPORTS: 'true', - ovn_const.LSP_OPTIONS_MCAST_FLOOD: 'false'}, + ovn_const.LSP_OPTIONS_MCAST_FLOOD: 'false', + ovn_const.LSP_OPTIONS_LOCALNET_LEARN_FDB: 'false'}, tag=300, type='localnet') segments = segments_db.get_network_segments( @@ -2977,7 +3060,7 @@ class TestOVNMechanismDriverSegment(MechDriverSetupBase, segment = self._test_create_segment( network_id=net['id'], physical_network='physnet1', segmentation_id=200, network_type='vlan')['segment'] - self._delete('segments', segment['id']) + self._delete('segments', segment['id'], as_admin=True) ovn_nb_api.delete_lswitch_port.assert_called_once_with( lport_name=ovn_utils.ovn_provnet_port_name(segment['id']), lswitch_name=ovn_utils.ovn_name(net['id'])) @@ -3005,12 +3088,12 @@ class TestOVNMechanismDriverSegment(MechDriverSetupBase, 'options': {'network_name': 'physnet2'}, 'tag': 300, 'name': ovn_utils.ovn_provnet_port_name(seg_2['id'])})] - self._delete('segments', seg_1['id']) + self._delete('segments', seg_1['id'], as_admin=True) ovn_nb_api.delete_lswitch_port.assert_called_once_with( lport_name=ovn_utils.ovn_provnet_port_name(net['id']), lswitch_name=ovn_utils.ovn_name(net['id'])) ovn_nb_api.delete_lswitch_port.reset_mock() - self._delete('segments', seg_2['id']) + self._delete('segments', seg_2['id'], as_admin=True) ovn_nb_api.delete_lswitch_port.assert_called_once_with( lport_name=ovn_utils.ovn_provnet_port_name(seg_2['id']), lswitch_name=ovn_utils.ovn_name(net['id'])) @@ -3114,8 +3197,8 @@ class TestOVNMechanismDriverSegment(MechDriverSetupBase, ovn_nb_api.delete_lswitch_port.assert_not_called() # Delete both segments - self._delete('segments', self.seg_2['id']) - self._delete('segments', self.seg_1['id']) + self._delete('segments', self.seg_2['id'], as_admin=True) + self._delete('segments', self.seg_1['id'], as_admin=True) # Make sure that the metadata port wasn't deleted. deleted_ports = [ @@ -3929,6 +4012,10 @@ class TestOVNMechanismDriverSecurityGroup(MechDriverSetupBase, self._test_create_port_with_vnic_type( portbindings.VNIC_BAREMETAL) + def test_create_port_with_vnic_virtio_forwarder(self): + self._test_create_port_with_vnic_type( + portbindings.VNIC_VIRTIO_FORWARDER) + def test_update_port_with_sgs(self): with self.network() as n, self.subnet(n): sg1 = self._create_empty_sg('sg1') @@ -4051,7 +4138,7 @@ class TestOVNMechanismDriverSecurityGroup(MechDriverSetupBase, 1, self.mech_driver.nb_ovn.pg_acl_del.call_count) def test_delete_port_with_security_groups_port_doesnt_remove_pg(self): - with self.network(set_context=True, tenant_id='test') as net1: + with self.network() as net1: with self.subnet(network=net1): sg = self._create_sg('sg') port = self._make_port( @@ -4129,21 +4216,15 @@ class TestOVNMechanismDriverMetadataPort(MechDriverSetupBase, """ self.mech_driver.nb_ovn.get_subnet_dhcp_options.return_value = { 'subnet': {}, 'ports': {}} - with self.network(set_context=True, tenant_id='test') as net1: + with self.network() as net1: with self.subnet(network=net1, cidr='10.0.0.0/24') as subnet1: - # Create a network:dhcp owner port just as how Neutron DHCP - # agent would do. - with self.port(subnet=subnet1, - device_owner=const.DEVICE_OWNER_DISTRIBUTED, - device_id='dhcpxxxx', - set_context=True, tenant_id='test'): - with self.subnet(network=net1, - cidr='20.0.0.0/24') as subnet2: - self.assertEqual( - 2, self.nb_ovn.set_lswitch_port.call_count) - args, kwargs = self.nb_ovn.set_lswitch_port.call_args - self.assertEqual(ovn_const.LSP_TYPE_LOCALPORT, - kwargs['type']) + with self.subnet(network=net1, + cidr='20.0.0.0/24') as subnet2: + self.assertEqual( + 2, self.nb_ovn.set_lswitch_port.call_count) + args, kwargs = self.nb_ovn.set_lswitch_port.call_args + self.assertEqual(ovn_const.LSP_TYPE_LOCALPORT, + kwargs['type']) port_ips = kwargs['external_ids'].get( ovn_const.OVN_CIDRS_EXT_ID_KEY, '').split() port_cidrs = [str(netaddr.IPNetwork(cidr).cidr) for cidr in port_ips] @@ -4176,6 +4257,7 @@ class TestOVNParentTagPortBinding(OVNMechanismDriverTestCase): self._create_port( self.fmt, n['network']['id'], expected_res_status=404, + is_admin=True, arg_list=(OVN_PROFILE,), **binding) @@ -4187,6 +4269,7 @@ class TestOVNParentTagPortBinding(OVNMechanismDriverTestCase): with self.port(s) as p: binding[OVN_PROFILE]['parent_name'] = p['port']['id'] res = self._create_port(self.fmt, n['network']['id'], + is_admin=True, arg_list=(OVN_PROFILE,), **binding) port = self.deserialize(self.fmt, res) @@ -4201,6 +4284,7 @@ class TestOVNParentTagPortBinding(OVNMechanismDriverTestCase): with self.port(s) as p: binding[OVN_PROFILE]['parent_name'] = p['port']['id'] self._create_port(self.fmt, n['network']['id'], + is_admin=True, arg_list=(OVN_PROFILE,), expected_res_status=400, **binding) @@ -4214,6 +4298,7 @@ class TestOVNVtepPortBinding(OVNMechanismDriverTestCase): with self.network() as n: with self.subnet(n): res = self._create_port(self.fmt, n['network']['id'], + is_admin=True, arg_list=(OVN_PROFILE,), **binding) port = self.deserialize(self.fmt, res) @@ -4225,6 +4310,7 @@ class TestOVNVtepPortBinding(OVNMechanismDriverTestCase): with self.network() as n: with self.subnet(n): self._create_port(self.fmt, n['network']['id'], + is_admin=True, arg_list=(OVN_PROFILE,), expected_res_status=400, **binding) @@ -4234,6 +4320,7 @@ class TestOVNVtepPortBinding(OVNMechanismDriverTestCase): with self.network() as n: with self.subnet(n): self._create_port(self.fmt, n['network']['id'], + is_admin=True, arg_list=(OVN_PROFILE,), expected_res_status=400, **binding) @@ -4244,6 +4331,7 @@ class TestOVNVtepPortBinding(OVNMechanismDriverTestCase): with self.network() as n: with self.subnet(n): self._create_port(self.fmt, n['network']['id'], + is_admin=True, arg_list=(OVN_PROFILE,), expected_res_status=400, **binding) @@ -4255,6 +4343,7 @@ class TestOVNVtepPortBinding(OVNMechanismDriverTestCase): with self.network() as n: with self.subnet(n): self._create_port(self.fmt, n['network']['id'], + is_admin=True, arg_list=(OVN_PROFILE,), expected_res_status=404, **binding) diff --git a/neutron/tests/unit/plugins/ml2/drivers/ovn/test_db_migration.py b/neutron/tests/unit/plugins/ml2/drivers/ovn/test_db_migration.py index ad7d56a39e..a14f3feb29 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/ovn/test_db_migration.py +++ b/neutron/tests/unit/plugins/ml2/drivers/ovn/test_db_migration.py @@ -39,10 +39,12 @@ class TestMigrateNeutronDatabaseToOvn( for sid in range(1, 6): net_arg = {pnet.NETWORK_TYPE: 'vxlan', pnet.SEGMENTATION_ID: sid} - network_id = self._make_network(self.fmt, 'net%d' % sid, True, + network_id = self._make_network( + self.fmt, 'net%d' % sid, True, as_admin=True, arg_list=(pnet.NETWORK_TYPE, pnet.SEGMENTATION_ID,), - **net_arg)['network']['id'] + **net_arg + )['network']['id'] for vif_details in vif_details_list: port = self._make_port(self.fmt, network_id)['port'] diff --git a/neutron/tests/unit/plugins/ml2/extensions/test_dns_domain_keywords.py b/neutron/tests/unit/plugins/ml2/extensions/test_dns_domain_keywords.py index e656e250f5..b658d96c1c 100644 --- a/neutron/tests/unit/plugins/ml2/extensions/test_dns_domain_keywords.py +++ b/neutron/tests/unit/plugins/ml2/extensions/test_dns_domain_keywords.py @@ -50,7 +50,7 @@ class DNSDomainKeywordsTestCase( net_kwargs.get('arg_list', ()) + (dns_apidef.DNSDOMAIN,) net_kwargs['shared'] = True res = self._create_network(self.fmt, 'test_network', True, - **net_kwargs) + as_admin=True, **net_kwargs) network = self.deserialize(self.fmt, res) if ipv4: cidr = '10.0.0.0/24' @@ -108,8 +108,8 @@ class DNSDomainKeywordsTestCase( # NOTE(slaweq): Admin context is required here to be able to update # fixed_ips of the port as by default it is not possible for non-admin # users - ctx = context.Context(project_id=PROJECT_ID, is_admin=True) - req = self.new_update_request('ports', data, port['id'], context=ctx) + req = self.new_update_request('ports', data, port['id'], + tenant_id=PROJECT_ID, as_admin=True) res = req.get_response(self.api) self.assertEqual(200, res.status_int) port = self.deserialize(self.fmt, res)['port'] diff --git a/neutron/tests/unit/plugins/ml2/extensions/test_dns_integration.py b/neutron/tests/unit/plugins/ml2/extensions/test_dns_integration.py index 75783ad0b4..702f2b612b 100644 --- a/neutron/tests/unit/plugins/ml2/extensions/test_dns_integration.py +++ b/neutron/tests/unit/plugins/ml2/extensions/test_dns_integration.py @@ -27,6 +27,7 @@ from oslo_config import cfg from oslo_utils import uuidutils import testtools +from neutron.common import config from neutron.objects import ports as port_obj from neutron.plugins.ml2.extensions import dns_integration from neutron.services.externaldns.drivers.designate import driver @@ -53,6 +54,7 @@ class DNSIntegrationTestCase(test_plugin.Ml2PluginV2TestCase): _domain = DNSDOMAIN def setUp(self): + config.register_common_config_options() cfg.CONF.set_override('extension_drivers', self._extension_drivers, group='ml2') @@ -80,7 +82,7 @@ class DNSIntegrationTestCase(test_plugin.Ml2PluginV2TestCase): net_kwargs['arg_list'] = \ net_kwargs.get('arg_list', ()) + (dns_apidef.DNSDOMAIN,) res = self._create_network(self.fmt, 'test_network', True, - **net_kwargs) + as_admin=True, **net_kwargs) network = self.deserialize(self.fmt, res) if ipv4: cidr = '10.0.0.0/24' diff --git a/neutron/tests/unit/plugins/ml2/extensions/test_tag_ports_during_bulk_creation.py b/neutron/tests/unit/plugins/ml2/extensions/test_tag_ports_during_bulk_creation.py index 6131f3611f..daa6e72542 100644 --- a/neutron/tests/unit/plugins/ml2/extensions/test_tag_ports_during_bulk_creation.py +++ b/neutron/tests/unit/plugins/ml2/extensions/test_tag_ports_during_bulk_creation.py @@ -50,12 +50,10 @@ class TagPortsDuringBulkCreationTestCase(test_plugin.Ml2PluginV2TestCase): def test_create_ports_bulk_with_tags(self): num_ports = 3 - tenant_id = 'some_tenant' - with self.network(tenant_id=tenant_id) as network_to_use: + with self.network() as network_to_use: net_id = network_to_use['network']['id'] port = {'port': {'network_id': net_id, - 'admin_state_up': True, - 'tenant_id': tenant_id}} + 'admin_state_up': True}} ports = [copy.deepcopy(port) for x in range(num_ports)] ports_tags_map = {} for port, tags in zip(ports, TAGS): @@ -73,13 +71,11 @@ class TagPortsDuringBulkCreationTestCase(test_plugin.Ml2PluginV2TestCase): def test_create_ports_bulk_no_tags(self): num_ports = 2 - tenant_id = 'some_tenant' - with self.network(tenant_id=tenant_id) as network_to_use: + with self.network() as network_to_use: net_id = network_to_use['network']['id'] port = {'port': {'name': 'port', 'network_id': net_id, - 'admin_state_up': True, - 'tenant_id': tenant_id}} + 'admin_state_up': True}} ports = [copy.deepcopy(port) for x in range(num_ports)] req_body = {'ports': ports} ports_req = self.new_create_request('ports', req_body) @@ -90,13 +86,11 @@ class TagPortsDuringBulkCreationTestCase(test_plugin.Ml2PluginV2TestCase): self.assertFalse(port['tags']) def test_create_port_with_tags(self): - tenant_id = 'some_tenant' - with self.network(tenant_id=tenant_id) as network_to_use: + with self.network() as network_to_use: net_id = network_to_use['network']['id'] req_body = {'port': {'name': 'port', 'network_id': net_id, 'admin_state_up': True, - 'tenant_id': tenant_id, 'tags': TAGS[0]}} port_req = self.new_create_request('ports', req_body) res = port_req.get_response(self.api) @@ -106,16 +100,14 @@ class TagPortsDuringBulkCreationTestCase(test_plugin.Ml2PluginV2TestCase): def test_type_args_passed_to_extension(self): num_ports = 2 - tenant_id = 'some_tenant' extension = tag_ports_during_bulk_creation with mock.patch.object( extension.TagPortsDuringBulkCreationExtensionDriver, 'process_create_port') as patched_method: - with self.network(tenant_id=tenant_id) as network_to_use: + with self.network() as network_to_use: net_id = network_to_use['network']['id'] port = {'port': {'network_id': net_id, - 'admin_state_up': True, - 'tenant_id': tenant_id}} + 'admin_state_up': True}} ports = [copy.deepcopy(port) for x in range(num_ports)] ports[0]['port']['tags'] = TAGS[0] ports[1]['port']['tags'] = TAGS[1] diff --git a/neutron/tests/unit/plugins/ml2/test_extension_driver_api.py b/neutron/tests/unit/plugins/ml2/test_extension_driver_api.py index d51a264527..2b673cf499 100644 --- a/neutron/tests/unit/plugins/ml2/test_extension_driver_api.py +++ b/neutron/tests/unit/plugins/ml2/test_extension_driver_api.py @@ -16,7 +16,6 @@ from neutron_lib import constants from neutron_lib import context from neutron_lib.plugins import directory from oslo_config import cfg -from oslo_utils import uuidutils from neutron.tests.unit.plugins.ml2.drivers import ext_test from neutron.tests.unit.plugins.ml2 import test_plugin @@ -35,9 +34,7 @@ class ExtensionDriverTestCase(test_plugin.Ml2PluginV2TestCase): self._ctxt = context.get_admin_context() def _verify_network_create(self, code, exc_reason): - tenant_id = uuidutils.generate_uuid() - data = {'network': {'name': 'net1', - 'tenant_id': tenant_id}} + data = {'network': {'name': 'net1'}} req = self.new_create_request('networks', data) res = req.get_response(self.api) self.assertEqual(code, res.status_int) @@ -47,7 +44,7 @@ class ExtensionDriverTestCase(test_plugin.Ml2PluginV2TestCase): self.assertEqual(exc_reason, network['NeutronError']['type']) - return (network, tenant_id) + return network def _verify_network_update(self, network, code, exc_reason): net_id = network['network']['id'] @@ -64,10 +61,9 @@ class ExtensionDriverTestCase(test_plugin.Ml2PluginV2TestCase): with mock.patch.object(ext_test.TestExtensionDriver, 'process_create_network', side_effect=TypeError): - net, tenant_id = self._verify_network_create(500, - 'HTTPInternalServerError') + self._verify_network_create(500, 'HTTPInternalServerError') # Verify the operation is rolled back - query_params = "tenant_id=%s" % tenant_id + query_params = "tenant_id=%s" % self._tenant_id nets = self._list('networks', query_params=query_params) self.assertFalse(nets['networks']) @@ -75,7 +71,7 @@ class ExtensionDriverTestCase(test_plugin.Ml2PluginV2TestCase): with mock.patch.object(ext_test.TestExtensionDriver, 'process_update_network', side_effect=TypeError): - network, tid = self._verify_network_create(201, None) + network = self._verify_network_create(201, None) self._verify_network_update(network, 500, 'HTTPInternalServerError') @@ -83,7 +79,7 @@ class ExtensionDriverTestCase(test_plugin.Ml2PluginV2TestCase): with mock.patch.object(ext_test.TestExtensionDriver, 'extend_network_dict', side_effect=[None, None, TypeError]): - network, tid = self._verify_network_create(201, None) + network = self._verify_network_create(201, None) self._verify_network_update(network, 400, 'ExtensionDriverError') def test_network_attr(self): diff --git a/neutron/tests/unit/plugins/ml2/test_plugin.py b/neutron/tests/unit/plugins/ml2/test_plugin.py index d355dac420..cd72574f0d 100644 --- a/neutron/tests/unit/plugins/ml2/test_plugin.py +++ b/neutron/tests/unit/plugins/ml2/test_plugin.py @@ -49,6 +49,7 @@ import webob from neutron._i18n import _ from neutron.agent import rpc as agent_rpc +from neutron.common import config from neutron.common import utils from neutron.db import agents_db from neutron.db import ipam_pluggable_backend @@ -381,7 +382,8 @@ class TestMl2NetworksV2(test_plugin.TestNetworksV2, for net_idx, net in enumerate(networks): # create req = self.new_create_request('networks', - {'network': net}) + {'network': net}, + as_admin=True) # verify network = self.deserialize(self.fmt, req.get_response(self.api))['network'] @@ -399,7 +401,8 @@ class TestMl2NetworksV2(test_plugin.TestNetworksV2, def _lookup_network_by_segmentation_id(self, seg_id, num_expected_nets): params_str = "%s=%s" % (pnet.SEGMENTATION_ID, seg_id) net_req = self.new_list_request('networks', None, - params=params_str) + params=params_str, + as_admin=True) networks = self.deserialize(self.fmt, net_req.get_response(self.api)) if num_expected_nets: self.assertIsNotNone(networks) @@ -446,9 +449,9 @@ class TestMl2NetworksV2(test_plugin.TestNetworksV2, plugin.type_manager, 'create_network_segments', side_effect=db_exc.RetryRequest(ValueError()) ) as f: - data = {'network': {'tenant_id': 'sometenant', 'name': 'dummy', + data = {'network': {'name': 'dummy', 'admin_state_up': True, 'shared': False}} - req = self.new_create_request('networks', data) + req = self.new_create_request('networks', data, as_admin=True) res = req.get_response(self.api) self.assertEqual(500, res.status_int) # 1 + retry count @@ -459,7 +462,7 @@ class TestMl2NetworksV2(test_plugin.TestNetworksV2, plugin = directory.get_plugin() kwargs = {'arg_list': (pnet.NETWORK_TYPE, ), pnet.NETWORK_TYPE: 'vlan'} - with self.network(**kwargs) as net: + with self.network(as_admin=True, **kwargs) as net: for attribute in set(pnet.ATTRIBUTES) - {pnet.SEGMENTATION_ID}: net_data = {attribute: net['network'][attribute]} self.assertIsNone( @@ -491,7 +494,8 @@ class TestMl2NetworksV2(test_plugin.TestNetworksV2, {pnet.NETWORK_TYPE: 'vlan', pnet.PHYSICAL_NETWORK: 'physnet2', pnet.SEGMENTATION_ID: 2}] - with self.network(**{'arg_list': (mpnet_apidef.SEGMENTS, ), + with self.network(as_admin=True, + **{'arg_list': (mpnet_apidef.SEGMENTS, ), mpnet_apidef.SEGMENTS: segments}) as net: self.assertRaises( exc.InvalidInput, plugin._update_segmentation_id, self.context, @@ -518,7 +522,8 @@ class TestMl2NetworksV2(test_plugin.TestNetworksV2, mock.patch.object(type(mech_driver), 'agent_type', new_callable=mock.PropertyMock(return_value=None)).start() - with self.network(**{'arg_list': (mpnet_apidef.SEGMENTS, ), + with self.network(as_admin=True, + **{'arg_list': (mpnet_apidef.SEGMENTS, ), mpnet_apidef.SEGMENTS: segments}) as net, \ mock.patch.object( port_obj.Port, 'check_network_ports_by_binding_types', @@ -598,7 +603,8 @@ class TestMl2NetworksV2AgentMechDrivers(Ml2PluginV2TestCase): segments = [{pnet.NETWORK_TYPE: 'vlan', pnet.PHYSICAL_NETWORK: 'physnet1', pnet.SEGMENTATION_ID: 1}] - with self.network(**{'arg_list': (mpnet_apidef.SEGMENTS, ), + with self.network(as_admin=True, + **{'arg_list': (mpnet_apidef.SEGMENTS, ), mpnet_apidef.SEGMENTS: segments}) as net, \ mock.patch.object( port_obj.Port, 'check_network_ports_by_binding_types', @@ -623,9 +629,8 @@ class TestExternalNetwork(Ml2PluginV2TestCase): def _create_external_network(self): data = {'network': {'name': 'net1', - 'router:external': 'True', - 'tenant_id': 'tenant_one'}} - network_req = self.new_create_request('networks', data) + 'router:external': 'True'}} + network_req = self.new_create_request('networks', data, as_admin=True) network = self.deserialize(self.fmt, network_req.get_response(self.api)) return network @@ -669,10 +674,10 @@ class TestMl2NetworksWithVlanTransparencyBase(TestMl2NetworksV2): mpnet_apidef.SEGMENTS: [{pnet.NETWORK_TYPE: 'vlan', pnet.PHYSICAL_NETWORK: 'physnet1'}], - 'tenant_id': 'tenant_one', 'vlan_transparent': 'True'}} def setUp(self, plugin=None): + config.register_common_config_options() cfg.CONF.set_override('vlan_transparent', True) super(TestMl2NetworksWithVlanTransparencyBase, self).setUp(plugin) @@ -685,7 +690,8 @@ class TestMl2NetworksWithVlanTransparency( with mock.patch.object(mech_test.TestMechanismDriver, 'check_vlan_transparency', return_value=False): - network_req = self.new_create_request('networks', self.data) + network_req = self.new_create_request( + 'networks', self.data, as_admin=True) res = network_req.get_response(self.api) self.assertEqual(500, res.status_int) error_result = self.deserialize(self.fmt, res)['NeutronError'] @@ -696,7 +702,8 @@ class TestMl2NetworksWithVlanTransparency( with mock.patch.object(mech_test.TestMechanismDriver, 'check_vlan_transparency', return_value=True): - network_req = self.new_create_request('networks', self.data) + network_req = self.new_create_request( + 'networks', self.data, as_admin=True) res = network_req.get_response(self.api) self.assertEqual(201, res.status_int) network = self.deserialize(self.fmt, res)['network'] @@ -713,7 +720,8 @@ class TestMl2NetworksWithVlanTransparencyAndMTU( return_value=True): cfg.CONF.set_override('path_mtu', 1000, group='ml2') cfg.CONF.set_override('global_physnet_mtu', 1000) - network_req = self.new_create_request('networks', self.data) + network_req = self.new_create_request( + 'networks', self.data, as_admin=True) res = network_req.get_response(self.api) self.assertEqual(201, res.status_int) network = self.deserialize(self.fmt, res)['network'] @@ -727,8 +735,7 @@ class TestMl2NetworksWithAvailabilityZone(TestMl2NetworksV2): def test_create_network_availability_zone(self): az_hints = ['az1', 'az2'] data = {'network': {'name': 'net1', - az_def.AZ_HINTS: az_hints, - 'tenant_id': 'tenant_one'}} + az_def.AZ_HINTS: az_hints}} with mock.patch.object(agents_db.AgentAvailabilityZoneMixin, 'validate_availability_zones'): network_req = self.new_create_request('networks', data) @@ -879,6 +886,7 @@ class TestMl2SubnetsV2(test_plugin.TestSubnetsV2, net_arg = {pnet.NETWORK_TYPE: 'vxlan', pnet.SEGMENTATION_ID: '1'} network = self._make_network(self.fmt, 'net1', True, + as_admin=True, arg_list=(pnet.NETWORK_TYPE, pnet.SEGMENTATION_ID,), **net_arg) @@ -1280,7 +1288,7 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase): def test_update_port_with_empty_data(self): ctx = context.get_admin_context() plugin = directory.get_plugin() - with self.port() as port: + with self.port(is_admin=True) as port: port_id = port['port']['id'] new_port = plugin.update_port(ctx, port_id, {"port": {}}) new_port.pop('standard_attr_id') @@ -1422,7 +1430,8 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase): data = {'port': {'mac_address': None}} with self.port() as port: current_mac = port['port']['mac_address'] - req = self.new_update_request('ports', data, port['port']['id']) + req = self.new_update_request( + 'ports', data, port['port']['id'], as_admin=True) self.assertEqual(200, req.get_response(self.api).status_int) new_mac = plugin.get_port(ctx, port['port']['id'])['mac_address'] self.assertNotEqual(current_mac, new_mac) @@ -1458,7 +1467,7 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase): l3plugin = directory.get_plugin(plugin_constants.L3) kwargs = {'arg_list': (extnet_apidef.EXTERNAL,), extnet_apidef.EXTERNAL: True} - with self.network(**kwargs) as n: + with self.network(as_admin=True, **kwargs) as n: with self.subnet(network=n, cidr='200.0.0.0/22'): l3plugin.create_floatingip( context.get_admin_context(), @@ -1488,24 +1497,23 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase): res, 'ports', webob.exc.HTTPServerError.code) def test_create_ports_bulk_with_sec_grp(self): - ctx = context.get_admin_context() plugin = directory.get_plugin() with self.network() as net,\ mock.patch.object(plugin.notifier, 'security_groups_member_updated') as m_upd: res = self._create_port_bulk(self.fmt, 3, net['network']['id'], - 'test', True, context=ctx) + 'test', True) ports = self.deserialize(self.fmt, res) if 'ports' in ports: used_sg = ports['ports'][0]['security_groups'] m_upd.assert_has_calls( - [mock.call(ctx, [sg]) for sg in used_sg], any_order=True) + [mock.call(mock.ANY, [sg]) for sg in used_sg], + any_order=True) else: self.assertTrue('ports' in ports) def test_create_ports_bulk_with_portbinding_attrs(self): - ctx = context.get_admin_context() with self.network() as net: overrides = {0: {portbindings.HOST_ID: 'host1', portbindings.VNIC_TYPE: 'direct', @@ -1514,7 +1522,7 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase): portbindings.VNIC_TYPE: 'macvtap', portbindings.PROFILE: {'bar': 'bar'}}} res = self._create_port_bulk(self.fmt, 2, net['network']['id'], - 'test', True, context=ctx, + 'test', True, as_admin=True, override=overrides) ports = self.deserialize(self.fmt, res)['ports'] self.assertCountEqual(['direct', 'macvtap'], @@ -1525,7 +1533,6 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase): [p[portbindings.HOST_ID] for p in ports]) def test_create_ports_bulk_with_sec_grp_member_provider_update(self): - ctx = context.get_admin_context() plugin = directory.get_plugin() bulk_mock_name = "security_groups_member_updated" with self.network() as net,\ @@ -1534,28 +1541,25 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase): net_id = net['network']['id'] data = [{ 'network_id': net_id, - 'tenant_id': self._tenant_id }, { 'network_id': net_id, - 'tenant_id': self._tenant_id, 'device_owner': constants.DEVICE_OWNER_DHCP } ] - res = self._create_bulk_from_list(self.fmt, 'port', - data, context=ctx) + res = self._create_bulk_from_list(self.fmt, 'port', data, + as_admin=True) ports = self.deserialize(self.fmt, res) used_sg = ports['ports'][0]['security_groups'] - m_upd.assert_called_with(ctx, used_sg) + m_upd.assert_called_with(mock.ANY, used_sg) m_upd.reset_mock() data[0]['device_owner'] = constants.DEVICE_OWNER_DHCP self._create_bulk_from_list(self.fmt, 'port', - data, context=ctx) + data, as_admin=True) self.assertFalse(m_upd.called) def test_create_ports_bulk_with_sec_grp_provider_update_ipv6(self): - ctx = context.get_admin_context() plugin = directory.get_plugin() fake_prefix = '2001:db8::/64' fake_gateway = 'fe80::1' @@ -1571,13 +1575,12 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase): net_id = net['network']['id'] data = [{ 'network_id': net_id, - 'tenant_id': self._tenant_id, 'fixed_ips': [{'subnet_id': snet_v6['subnet']['id']}], 'device_owner': constants.DEVICE_OWNER_ROUTER_INTF } ] self._create_bulk_from_list(self.fmt, 'port', - data, context=ctx) + data, as_admin=True) self.assertFalse(m_upd.called) def test_create_ports_bulk_ip_allocation_reverted_in_case_of_error(self): @@ -1842,7 +1845,8 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase): port_kwargs = {portbindings.HOST_ID: 'host1', 'subnet': subnet, 'device_id': 'deadlocktest'} - with self.port(arg_list=(portbindings.HOST_ID,), + with self.port(is_admin=True, + arg_list=(portbindings.HOST_ID,), **port_kwargs) as port: self.assertTrue(port['port']['id']) self.assertTrue(get_port_mock.called) @@ -2037,7 +2041,8 @@ class TestMl2PortsV2WithRevisionPlugin(Ml2PluginV2TestCase): ctx = context.get_admin_context() plugin = directory.get_plugin() host_arg = {portbindings.HOST_ID: HOST} - with self.port(arg_list=(portbindings.HOST_ID,), + with self.port(is_admin=True, + arg_list=(portbindings.HOST_ID,), **host_arg) as port: port = plugin.get_port(ctx, port['port']['id']) updated_ports = [] @@ -2066,7 +2071,8 @@ class TestMl2PortsV2WithRevisionPlugin(Ml2PluginV2TestCase): registry.subscribe(creceiver, resources.PORT, events.AFTER_CREATE) host_arg = {portbindings.HOST_ID: HOST} - with self.port(arg_list=(portbindings.HOST_ID,), + with self.port(is_admin=True, + arg_list=(portbindings.HOST_ID,), **host_arg): self.assertGreater(updated_ports[0]['revision_number'], created_ports[0]['revision_number']) @@ -2079,7 +2085,8 @@ class TestMl2PortsV2WithRevisionPlugin(Ml2PluginV2TestCase): registry.subscribe(p_update_receiver, resources.PORT, events.AFTER_UPDATE) host_arg = {portbindings.HOST_ID: HOST} - with self.port(device_owner=constants.DEVICE_OWNER_DVR_INTERFACE, + with self.port(is_admin=True, + device_owner=constants.DEVICE_OWNER_DVR_INTERFACE, device_id=TEST_ROUTER_ID, arg_list=(portbindings.HOST_ID,), **host_arg) as port: @@ -2116,7 +2123,8 @@ class TestMl2PortsV2WithL3(test_plugin.TestPortsV2, Ml2PluginV2TestCase): host_arg = {portbindings.HOST_ID: HOST} with mock.patch.object(l3plugin.l3_rpc_notifier, 'routers_updated_on_host') as mock_updated: - with self.port(device_owner=constants.DEVICE_OWNER_ROUTER_HA_INTF, + with self.port(is_admin=True, + device_owner=constants.DEVICE_OWNER_ROUTER_HA_INTF, device_id=TEST_ROUTER_ID, arg_list=(portbindings.HOST_ID,), **host_arg) as port: @@ -2399,7 +2407,7 @@ class TestMl2DvrPortsV2(TestMl2PortsV2): if floating_ip: router_ids.add(ns_to_delete['router_id']) - with self.port() as port, \ + with self.port(is_admin=True) as port, \ mock.patch.object(registry, 'publish') as publish, \ mock.patch.object(self.l3plugin, 'disassociate_floatingips', @@ -2442,7 +2450,8 @@ class TestMl2DvrPortsV2(TestMl2PortsV2): def test_delete_port_with_floatingip_create_precommit_event(self): fake_method = mock.Mock() - with self.port(device_owner='network:floatingip') as port: + with self.port(is_admin=True, + device_owner='network:floatingip') as port: try: registry.subscribe(fake_method, resources.FLOATING_IP, events.PRECOMMIT_DELETE) @@ -2534,6 +2543,7 @@ class TestMl2PortBinding(Ml2PluginV2TestCase, profile_arg = {portbindings.PROFILE: {'d': s}} try: with self.port(expected_res_status=400, + is_admin=True, arg_list=(portbindings.PROFILE,), **profile_arg): pass @@ -2543,15 +2553,17 @@ class TestMl2PortBinding(Ml2PluginV2TestCase, def test_remove_port_binding_profile(self): profile = {'e': 5} profile_arg = {portbindings.PROFILE: profile} - with self.port(arg_list=(portbindings.PROFILE,), + with self.port(is_admin=True, + arg_list=(portbindings.PROFILE,), **profile_arg) as port: self._check_port_binding_profile(port['port'], profile) port_id = port['port']['id'] profile_arg = {portbindings.PROFILE: None} port = self._update('ports', port_id, - {'port': profile_arg})['port'] + {'port': profile_arg}, + as_admin=True)['port'] self._check_port_binding_profile(port) - port = self._show('ports', port_id)['port'] + port = self._show('ports', port_id, as_admin=True)['port'] self._check_port_binding_profile(port) def test_return_on_concurrent_delete_and_binding(self): @@ -2744,15 +2756,17 @@ class TestMl2PortBinding(Ml2PluginV2TestCase, def test_port_binding_profile_not_changed(self): profile = {'e': 5} profile_arg = {portbindings.PROFILE: profile} - with self.port(arg_list=(portbindings.PROFILE,), + with self.port(is_admin=True, + arg_list=(portbindings.PROFILE,), **profile_arg) as port: self._check_port_binding_profile(port['port'], profile) port_id = port['port']['id'] state_arg = {'admin_state_up': True} port = self._update('ports', port_id, - {'port': state_arg})['port'] + {'port': state_arg}, + as_admin=True)['port'] self._check_port_binding_profile(port, profile) - port = self._show('ports', port_id)['port'] + port = self._show('ports', port_id, as_admin=True)['port'] self._check_port_binding_profile(port, profile) def test_update_port_binding_host_id_none(self): @@ -2885,8 +2899,7 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): super(TestMultiSegmentNetworks, self).setUp() def test_allocate_dynamic_segment(self): - data = {'network': {'name': 'net1', - 'tenant_id': 'tenant_one'}} + data = {'network': {'name': 'net1'}} network_req = self.new_create_request('networks', data) network = self.deserialize(self.fmt, network_req.get_response(self.api)) @@ -2914,8 +2927,7 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): self.assertEqual(dynamic_segment[driver_api.SEGMENTATION_ID], 1234) def test_allocate_dynamic_segment_multiple_physnets(self): - data = {'network': {'name': 'net1', - 'tenant_id': 'tenant_one'}} + data = {'network': {'name': 'net1'}} network_req = self.new_create_request('networks', data) network = self.deserialize(self.fmt, network_req.get_response(self.api)) @@ -2950,8 +2962,7 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): segment = {driver_api.NETWORK_TYPE: 'vlan', driver_api.PHYSICAL_NETWORK: physnet_name} - data = {'network': {'name': 'net1', - 'tenant_id': 'tenant_one'}} + data = {'network': {'name': 'net1'}} network_req = self.new_create_request('networks', data) network = self.deserialize(self.fmt, network_req.get_response(self.api)) @@ -3000,8 +3011,7 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): self.assertEqual(1, len(allocs)) def test_allocate_release_dynamic_segment(self): - data = {'network': {'name': 'net1', - 'tenant_id': 'tenant_one'}} + data = {'network': {'name': 'net1'}} network_req = self.new_create_request('networks', data) network = self.deserialize(self.fmt, network_req.get_response(self.api)) @@ -3026,9 +3036,8 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): data = {'network': {'name': 'net1', pnet.NETWORK_TYPE: 'vlan', pnet.PHYSICAL_NETWORK: 'physnet1', - pnet.SEGMENTATION_ID: 1, - 'tenant_id': 'tenant_one'}} - network_req = self.new_create_request('networks', data) + pnet.SEGMENTATION_ID: 1}} + network_req = self.new_create_request('networks', data, as_admin=True) network = self.deserialize(self.fmt, network_req.get_response(self.api)) self.assertEqual('vlan', network['network'][pnet.NETWORK_TYPE]) @@ -3039,9 +3048,8 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): def test_fail_update_network_provider_attr(self): data = {'network': {'name': 'net1', pnet.NETWORK_TYPE: 'flat', - pnet.PHYSICAL_NETWORK: 'physnet1', - 'tenant_id': 'tenant_one'}} - network_req = self.new_create_request('networks', data) + pnet.PHYSICAL_NETWORK: 'physnet1'}} + network_req = self.new_create_request('networks', data, as_admin=True) network = self.deserialize(self.fmt, network_req.get_response(self.api)) self.assertEqual('flat', network['network'][pnet.NETWORK_TYPE]) @@ -3051,7 +3059,8 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): pnet.NETWORK_TYPE: 'flat', pnet.PHYSICAL_NETWORK: 'update_physnet1'}} network_req = self.new_update_request('networks', data, - network['network']['id']) + network['network']['id'], + as_admin=True) network = self.deserialize(self.fmt, network_req.get_response(self.api)) self.assertIn('NeutronError', network) @@ -3063,9 +3072,8 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): def test_update_network_provider_attr_no_change(self): data = {'network': {'name': 'net1', pnet.NETWORK_TYPE: 'flat', - pnet.PHYSICAL_NETWORK: 'physnet1', - 'tenant_id': 'tenant_one'}} - network_req = self.new_create_request('networks', data) + pnet.PHYSICAL_NETWORK: 'physnet1'}} + network_req = self.new_create_request('networks', data, as_admin=True) network = self.deserialize(self.fmt, network_req.get_response(self.api)) self.assertEqual('flat', network['network'][pnet.NETWORK_TYPE]) @@ -3075,7 +3083,8 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): pnet.NETWORK_TYPE: 'flat', pnet.PHYSICAL_NETWORK: 'physnet1'}} network_req = self.new_update_request('networks', data, - network['network']['id']) + network['network']['id'], + as_admin=True) network = self.deserialize(self.fmt, network_req.get_response(self.api)) self.assertEqual('updated-net1', network['network']['name']) @@ -3085,9 +3094,8 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): mpnet_apidef.SEGMENTS: [{pnet.NETWORK_TYPE: 'vlan', pnet.PHYSICAL_NETWORK: 'physnet1', - pnet.SEGMENTATION_ID: 1}], - 'tenant_id': 'tenant_one'}} - net_req = self.new_create_request('networks', data) + pnet.SEGMENTATION_ID: 1}]}} + net_req = self.new_create_request('networks', data, as_admin=True) network = self.deserialize(self.fmt, net_req.get_response(self.api)) self.assertEqual('vlan', network['network'][pnet.NETWORK_TYPE]) self.assertEqual('physnet1', network['network'][pnet.PHYSICAL_NETWORK]) @@ -3095,7 +3103,8 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): self.assertNotIn(mpnet_apidef.SEGMENTS, network['network']) # Tests get_network() - net_req = self.new_show_request('networks', network['network']['id']) + net_req = self.new_show_request('networks', network['network']['id'], + as_admin=True) network = self.deserialize(self.fmt, net_req.get_response(self.api)) self.assertEqual('vlan', network['network'][pnet.NETWORK_TYPE]) self.assertEqual('physnet1', network['network'][pnet.PHYSICAL_NETWORK]) @@ -3110,9 +3119,8 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): pnet.SEGMENTATION_ID: 1}, {pnet.NETWORK_TYPE: 'vlan', pnet.PHYSICAL_NETWORK: 'physnet2', - pnet.SEGMENTATION_ID: 2}], - 'tenant_id': 'tenant_one'}} - network_req = self.new_create_request('networks', data) + pnet.SEGMENTATION_ID: 2}]}} + network_req = self.new_create_request('networks', data, as_admin=True) network = self.deserialize(self.fmt, network_req.get_response(self.api)) segments = network['network'][mpnet_apidef.SEGMENTS] @@ -3124,7 +3132,8 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): segments[segment_index][field]) # Tests get_network() - net_req = self.new_show_request('networks', network['network']['id']) + net_req = self.new_show_request('networks', network['network']['id'], + as_admin=True) network = self.deserialize(self.fmt, net_req.get_response(self.api)) segments = network['network'][mpnet_apidef.SEGMENTS] for segment_index, segment in enumerate(data['network'] @@ -3157,9 +3166,8 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): pnet.SEGMENTATION_ID: 1}, {pnet.NETWORK_TYPE: 'vlan', pnet.PHYSICAL_NETWORK: 'physnet1', - pnet.SEGMENTATION_ID: 1}], - 'tenant_id': 'tenant_one'}} - network_req = self.new_create_request('networks', data) + pnet.SEGMENTATION_ID: 1}]}} + network_req = self.new_create_request('networks', data, as_admin=True) res = network_req.get_response(self.api) self.assertEqual(400, res.status_int) @@ -3169,11 +3177,10 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): [{pnet.NETWORK_TYPE: 'vlan', pnet.PHYSICAL_NETWORK: 'physnet1'}, {pnet.NETWORK_TYPE: 'vlan', - pnet.PHYSICAL_NETWORK: 'physnet1'}], - 'tenant_id': 'tenant_one'}} + pnet.PHYSICAL_NETWORK: 'physnet1'}]}} retry_fixture = fixture.DBRetryErrorsFixture(max_retries=2) retry_fixture.setUp() - network_req = self.new_create_request('networks', data) + network_req = self.new_create_request('networks', data, as_admin=True) res = network_req.get_response(self.api) self.assertEqual(201, res.status_int) @@ -3183,9 +3190,8 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): 'shared': False, pnet.NETWORK_TYPE: 'vlan', pnet.PHYSICAL_NETWORK: 'physnet1', - pnet.SEGMENTATION_ID: 1, - 'tenant_id': 'tenant_one'}} - network_req = self.new_create_request('networks', data) + pnet.SEGMENTATION_ID: 1}} + network_req = self.new_create_request('networks', data, as_admin=True) res = network_req.get_response(self.api) network = self.deserialize(self.fmt, res) network_id = network['network']['id'] @@ -3217,9 +3223,8 @@ class TestMultiSegmentNetworks(Ml2PluginV2TestCase): 'shared': False, pnet.NETWORK_TYPE: 'vlan', pnet.PHYSICAL_NETWORK: 'physnet1', - pnet.SEGMENTATION_ID: 1, - 'tenant_id': 'tenant_one'}} - network_req = self.new_create_request('networks', data) + pnet.SEGMENTATION_ID: 1}} + network_req = self.new_create_request('networks', data, as_admin=True) res = network_req.get_response(self.api) network = self.deserialize(self.fmt, res) network_id = network['network']['id'] @@ -3394,9 +3399,7 @@ class TestFaultyMechansimDriver(Ml2PluginV2FaultyDriverTestCase): 'create_network_postcommit', side_effect=(exc.InvalidInput( error_message=err_msg))): - tenant_id = uuidutils.generate_uuid() - data = {'network': {'name': 'net1', - 'tenant_id': tenant_id}} + data = {'network': {'name': 'net1'}} req = self.new_create_request('networks', data) res = req.get_response(self.api) self.assertEqual(400, res.status_int) @@ -3405,7 +3408,7 @@ class TestFaultyMechansimDriver(Ml2PluginV2FaultyDriverTestCase): error['NeutronError']['type']) # Check the client can see the root cause of error. self.assertIn(err_msg, error['NeutronError']['message']) - query_params = "tenant_id=%s" % tenant_id + query_params = "tenant_id=%s" % self._tenant_id nets = self._list('networks', query_params=query_params) self.assertFalse(nets['networks']) @@ -3417,8 +3420,7 @@ class TestFaultyMechansimDriver(Ml2PluginV2FaultyDriverTestCase): with mock.patch.object(mech_logger.LoggerMechanismDriver, 'delete_network_postcommit') as dnp: - data = {'network': {'name': 'net1', - 'tenant_id': 'tenant_one'}} + data = {'network': {'name': 'net1'}} network_req = self.new_create_request('networks', data) network_res = network_req.get_response(self.api) self.assertEqual(201, network_res.status_int) @@ -3442,8 +3444,7 @@ class TestFaultyMechansimDriver(Ml2PluginV2FaultyDriverTestCase): with mock.patch.object(mech_logger.LoggerMechanismDriver, 'update_network_postcommit') as unp: - data = {'network': {'name': 'net1', - 'tenant_id': 'tenant_one'}} + data = {'network': {'name': 'net1'}} network_req = self.new_create_request('networks', data) network_res = network_req.get_response(self.api) self.assertEqual(201, network_res.status_int) @@ -3481,8 +3482,6 @@ class TestFaultyMechansimDriver(Ml2PluginV2FaultyDriverTestCase): 'cidr': '10.0.20.0/24', 'ip_version': constants.IP_VERSION_4, 'name': 'subnet1', - 'tenant_id': - network['network']['tenant_id'], 'gateway_ip': '10.0.20.1'}} req = self.new_create_request('subnets', data) res = req.get_response(self.api) @@ -3510,8 +3509,6 @@ class TestFaultyMechansimDriver(Ml2PluginV2FaultyDriverTestCase): 'cidr': '10.0.20.0/24', 'ip_version': constants.IP_VERSION_4, 'name': 'subnet1', - 'tenant_id': - network['network']['tenant_id'], 'gateway_ip': '10.0.20.1'}} subnet_req = self.new_create_request('subnets', data) subnet_res = subnet_req.get_response(self.api) @@ -3543,8 +3540,6 @@ class TestFaultyMechansimDriver(Ml2PluginV2FaultyDriverTestCase): 'cidr': '10.0.20.0/24', 'ip_version': constants.IP_VERSION_4, 'name': 'subnet1', - 'tenant_id': - network['network']['tenant_id'], 'gateway_ip': '10.0.20.1'}} subnet_req = self.new_create_request('subnets', data) subnet_res = subnet_req.get_response(self.api) @@ -3579,8 +3574,6 @@ class TestFaultyMechansimDriver(Ml2PluginV2FaultyDriverTestCase): with self.network() as network: net_id = network['network']['id'] data = {'port': {'network_id': net_id, - 'tenant_id': - network['network']['tenant_id'], 'name': 'port1', 'admin_state_up': 1, 'fixed_ips': []}} @@ -3606,8 +3599,6 @@ class TestFaultyMechansimDriver(Ml2PluginV2FaultyDriverTestCase): with self.network() as network: data = {'port': {'network_id': network['network']['id'], - 'tenant_id': - network['network']['tenant_id'], 'name': 'port1', 'admin_state_up': 1, 'fixed_ips': []}} @@ -3655,8 +3646,6 @@ class TestFaultyMechansimDriver(Ml2PluginV2FaultyDriverTestCase): subnet_id = subnet['subnet']['id'] data = {'port': { 'network_id': network['network']['id'], - 'tenant_id': - network['network']['tenant_id'], 'name': 'port1', 'device_owner': constants.DEVICE_OWNER_DVR_INTERFACE, @@ -3691,7 +3680,7 @@ class TestML2PluggableIPAM(test_ipam.UseIpamMixin, TestMl2SubnetsV2): request.subnet_cidr = netaddr.IPNetwork(cidr) request.allocation_pools = [] request.gateway_ip = netaddr.IPAddress(gateway_ip) - request.tenant_id = uuidutils.generate_uuid() + request.tenant_id = self._tenant_id ipam_subnet = mock.Mock() ipam_subnet.get_details.return_value = request @@ -3910,7 +3899,8 @@ class TestML2Segments(Ml2PluginV2TestCase): driver_api.PHYSICAL_NETWORK: physical_network, driver_api.SEGMENTATION_ID: segmentation_id} - with self.network(**{'arg_list': (mpnet_apidef.SEGMENTS, ), + with self.network(as_admin=True, + **{'arg_list': (mpnet_apidef.SEGMENTS, ), mpnet_apidef.SEGMENTS: network_segments})\ as test_network: multisegment_network = test_network['network'] @@ -3942,7 +3932,8 @@ class TestML2Segments(Ml2PluginV2TestCase): driver_api.PHYSICAL_NETWORK: physical_network, driver_api.SEGMENTATION_ID: segmentation_id} - with self.network(**{'arg_list': (mpnet_apidef.SEGMENTS, ), + with self.network(as_admin=True, + **{'arg_list': (mpnet_apidef.SEGMENTS, ), mpnet_apidef.SEGMENTS: network_segments})\ as test_network: multisegment_network = test_network['network'] @@ -3968,7 +3959,7 @@ class TestML2Segments(Ml2PluginV2TestCase): pnet.PHYSICAL_NETWORK: physical_network, pnet.SEGMENTATION_ID: segmentation_id} - with self.network() as test_network: + with self.network(as_admin=True) as test_network: # network() implicitaly creates a single segment single_segment_network = test_network['network'] observed_network = self.driver._build_original_network( diff --git a/neutron/tests/unit/plugins/ml2/test_port_binding.py b/neutron/tests/unit/plugins/ml2/test_port_binding.py index cf5db88eff..dcca1b6f62 100644 --- a/neutron/tests/unit/plugins/ml2/test_port_binding.py +++ b/neutron/tests/unit/plugins/ml2/test_port_binding.py @@ -78,7 +78,8 @@ class PortBindingTestCase(test_plugin.NeutronDbPluginV2TestCase): mac_address = 'aa:aa:aa:aa:aa:aa' host_arg = {portbindings.HOST_ID: host, 'mac_address': mac_address} - with self.port(name='name', arg_list=(portbindings.HOST_ID,), + with self.port(name='name', is_admin=True, + arg_list=(portbindings.HOST_ID,), **host_arg) as port: self._check_response(port['port'], vif_type, has_port_filter, bound, status) @@ -152,12 +153,12 @@ class PortBindingTestCase(test_plugin.NeutronDbPluginV2TestCase): update_body = {'name': 'test_update'} if new_host is not None: update_body[portbindings.HOST_ID] = new_host - with self.port(name='name', arg_list=(portbindings.HOST_ID,), + with self.port(name='name', is_admin=True, + arg_list=(portbindings.HOST_ID,), **host_arg) as port: - neutron_context = context.get_admin_context() updated_port = self._update('ports', port['port']['id'], {'port': update_body}, - neutron_context=neutron_context) + as_admin=True) port_data = updated_port['port'] if new_host is not None: self.assertEqual(new_host, @@ -190,7 +191,7 @@ class PortBindingTestCase(test_plugin.NeutronDbPluginV2TestCase): ctx = context.get_admin_context() plugin = directory.get_plugin() host_id = {portbindings.HOST_ID: 'host1'} - with self.port(**host_id) as port: + with self.port(is_admin=True, **host_id) as port: # Since the port is DOWN at first # It's necessary to make its status ACTIVE for this test plugin.update_port_status(ctx, port['port']['id'], @@ -221,7 +222,8 @@ class PortBindingTestCase(test_plugin.NeutronDbPluginV2TestCase): def test_distributed_binding(self): ctx = context.get_admin_context() - with self.port(device_owner=const.DEVICE_OWNER_DVR_INTERFACE) as port: + with self.port(is_admin=True, + device_owner=const.DEVICE_OWNER_DVR_INTERFACE) as port: port_id = port['port']['id'] # Verify port's VIF type and status. @@ -235,7 +237,7 @@ class PortBindingTestCase(test_plugin.NeutronDbPluginV2TestCase): 'device_id': 'router1'}}) # Get port and verify VIF type and status unchanged. - port = self._show('ports', port_id) + port = self._show('ports', port_id, as_admin=True) self.assertEqual(portbindings.VIF_TYPE_DISTRIBUTED, port['port'][portbindings.VIF_TYPE]) self.assertEqual('DOWN', port['port']['status']) @@ -247,7 +249,7 @@ class PortBindingTestCase(test_plugin.NeutronDbPluginV2TestCase): self.assertEqual('local', details['network_type']) # Get port and verify VIF type and changed status. - port = self._show('ports', port_id) + port = self._show('ports', port_id, as_admin=True) self.assertEqual(portbindings.VIF_TYPE_DISTRIBUTED, port['port'][portbindings.VIF_TYPE]) self.assertEqual('BUILD', port['port']['status']) @@ -258,7 +260,7 @@ class PortBindingTestCase(test_plugin.NeutronDbPluginV2TestCase): host='host-ovs-no_filter') # Get port and verify VIF type and changed status. - port = self._show('ports', port_id) + port = self._show('ports', port_id, as_admin=True) self.assertEqual(portbindings.VIF_TYPE_DISTRIBUTED, port['port'][portbindings.VIF_TYPE]) self.assertEqual('ACTIVE', port['port']['status']) @@ -269,7 +271,7 @@ class PortBindingTestCase(test_plugin.NeutronDbPluginV2TestCase): host='host-ovs-no_filter') # Get port and verify VIF type and changed status. - port = self._show('ports', port_id) + port = self._show('ports', port_id, as_admin=True) self.assertEqual(portbindings.VIF_TYPE_DISTRIBUTED, port['port'][portbindings.VIF_TYPE]) self.assertEqual('DOWN', port['port']['status']) @@ -382,7 +384,8 @@ class ExtendedPortBindingTestCase(test_plugin.NeutronDbPluginV2TestCase): data = {'binding': kwargs} binding_req = self.new_update_request('ports', data, port_id, fmt, subresource='bindings', - sub_id=host) + sub_id=host, + as_admin=True) return binding_req.get_response(self.api) def _do_update_port_binding(self, fmt, port_id, host, **kwargs): @@ -457,7 +460,8 @@ class ExtendedPortBindingTestCase(test_plugin.NeutronDbPluginV2TestCase): def test_create_duplicate_port_binding(self): device_owner = '%s%s' % (const.DEVICE_OWNER_COMPUTE_PREFIX, 'nova') host_arg = {portbindings.HOST_ID: self.host} - with self.port(device_owner=device_owner, + with self.port(is_admin=True, + device_owner=device_owner, arg_list=(portbindings.HOST_ID,), **host_arg) as port: response = self._create_port_binding(self.fmt, port['port']['id'], @@ -540,7 +544,7 @@ class ExtendedPortBindingTestCase(test_plugin.NeutronDbPluginV2TestCase): active_binding = self._activate_port_binding( port['id'], self.host, raw_response=False) self._assert_bound_port_binding(active_binding) - updated_port = self._show('ports', port['id'])['port'] + updated_port = self._show('ports', port['id'], as_admin=True)['port'] updated_bound_drivers = updated_port[portbindings.VIF_DETAILS].pop( portbindings.VIF_DETAILS_BOUND_DRIVERS) self.assertEqual({'0': 'test'}, updated_bound_drivers) @@ -711,7 +715,8 @@ class ExtendedPortBindingTestCase(test_plugin.NeutronDbPluginV2TestCase): with mock.patch.object( mechanism_test.TestMechanismDriver, '_check_port_context' ): - req = self.new_update_request('ports', update_body, port_id) + req = self.new_update_request('ports', update_body, port_id, + as_admin=True) self.assertEqual(200, req.get_response(self.api).status_int) def test_bind_non_pf_port_with_mac_port_not_updated(self): @@ -851,7 +856,8 @@ class ExtendedPortBindingTestCase(test_plugin.NeutronDbPluginV2TestCase): with mock.patch.object( mechanism_test.TestMechanismDriver, '_check_port_context' ): - req = self.new_update_request('ports', update_body, port['id']) + req = self.new_update_request('ports', update_body, port['id'], + as_admin=True) self.assertEqual(200, req.get_response(self.api).status_int) # Neutron expected to reset the MAC to a generated one so that the diff --git a/neutron/tests/unit/plugins/ml2/test_security_group.py b/neutron/tests/unit/plugins/ml2/test_security_group.py index 3de28b6294..494059abe5 100644 --- a/neutron/tests/unit/plugins/ml2/test_security_group.py +++ b/neutron/tests/unit/plugins/ml2/test_security_group.py @@ -159,7 +159,8 @@ class TestMl2SecurityGroups(Ml2SecurityGroupsTestCase, self.assertFalse(self.was_active) self._delete( 'security-groups', - self._list('security-groups')['security_groups'][0]['id']) + self._list('security-groups')['security_groups'][0]['id'], + as_admin=True) with self.port(subnet=s): self.assertFalse(self.was_active) diff --git a/neutron/tests/unit/plugins/ml2/test_tracked_resources.py b/neutron/tests/unit/plugins/ml2/test_tracked_resources.py index 264dd8e908..5d5d1c1dd5 100644 --- a/neutron/tests/unit/plugins/ml2/test_tracked_resources.py +++ b/neutron/tests/unit/plugins/ml2/test_tracked_resources.py @@ -233,9 +233,8 @@ class TestTrackedResources(BaseTestTrackedResources): def test_list_networks_clears_dirty(self): self._test_init('network') - net = self._make_network('json', 'meh', True)['network'] - self.ctx.project_id = net['project_id'] - self._list('networks', neutron_context=self.ctx) + self._make_network('json', 'meh', True)['network'] + self._list('networks', as_admin=True) self._verify_dirty_bit('network', expected_value=False) def test_create_delete_port_marks_dirty(self): @@ -252,9 +251,8 @@ class TestTrackedResources(BaseTestTrackedResources): def test_list_ports_clears_dirty(self): self._test_init('port') net = self._make_network('json', 'meh', True)['network'] - port = self._make_port('json', net['id'])['port'] - self.ctx.project_id = port['project_id'] - self._list('ports', neutron_context=self.ctx) + self._make_port('json', net['id'])['port'] + self._list('ports', as_admin=True) self._verify_dirty_bit('port', expected_value=False) def test_create_delete_subnet_marks_dirty(self): @@ -286,17 +284,14 @@ class TestTrackedResources(BaseTestTrackedResources): def test_list_subnets_clears_dirty(self): self._test_init('subnet') net = self._make_network('json', 'meh', True) - subnet = self._make_subnet('json', net, '10.0.0.1', - '10.0.0.0/24')['subnet'] - self.ctx.project_id = subnet['project_id'] - self._list('subnets', neutron_context=self.ctx) + self._make_subnet('json', net, '10.0.0.1', '10.0.0.0/24')['subnet'] + self._list('subnets', as_admin=True) self._verify_dirty_bit('subnet', expected_value=False) def test_create_delete_subnetpool_marks_dirty(self): self._test_init('subnetpool') pool = self._make_subnetpool('json', ['10.0.0.0/8'], - name='meh', - tenant_id=self._project_id)['subnetpool'] + name='meh')['subnetpool'] self._verify_dirty_bit('subnetpool') # Clear the dirty bit quota_db_api.set_quota_usage_dirty( @@ -306,17 +301,14 @@ class TestTrackedResources(BaseTestTrackedResources): def test_list_subnetpools_clears_dirty(self): self._test_init('subnetpool') - pool = self._make_subnetpool('json', ['10.0.0.0/8'], - name='meh', - tenant_id=self._project_id)['subnetpool'] - self.ctx.project_id = pool['project_id'] - self._list('subnetpools', neutron_context=self.ctx) + self._make_subnetpool('json', ['10.0.0.0/8'], name='meh')['subnetpool'] + self._list('subnetpools', as_admin=True) self._verify_dirty_bit('subnetpool', expected_value=False) def test_create_delete_securitygroup_marks_dirty(self): self._test_init('security_group') sec_group = self._make_security_group( - 'json', 'meh', 'meh', tenant_id=self._project_id)['security_group'] + 'json', 'meh', 'meh')['security_group'] self._verify_dirty_bit('security_group') # Clear the dirty bit quota_db_api.set_quota_usage_dirty( @@ -327,17 +319,16 @@ class TestTrackedResources(BaseTestTrackedResources): def test_list_securitygroups_clears_dirty(self): self._test_init('security_group') self._make_security_group( - 'json', 'meh', 'meh', tenant_id=self._project_id)['security_group'] - self.ctx.project_id = self._project_id - self._list('security-groups', neutron_context=self.ctx) + 'json', 'meh', 'meh',)['security_group'] + self._list('security-groups', as_admin=True) self._verify_dirty_bit('security_group', expected_value=False) def test_create_delete_securitygrouprule_marks_dirty(self): self._test_init('security_group_rule') sec_group = self._make_security_group( - 'json', 'meh', 'meh', tenant_id=self._project_id)['security_group'] + 'json', 'meh', 'meh')['security_group'] rule_req = self._build_security_group_rule( - sec_group['id'], 'ingress', 'TCP', tenant_id=self._project_id) + sec_group['id'], 'ingress', 'TCP') sec_group_rule = self._make_security_group_rule( 'json', rule_req)['security_group_rule'] self._verify_dirty_bit('security_group_rule') @@ -349,10 +340,8 @@ class TestTrackedResources(BaseTestTrackedResources): def test_list_securitygrouprules_clears_dirty(self): self._test_init('security_group_rule') - self._make_security_group( - 'json', 'meh', 'meh', tenant_id=self._project_id)['security_group'] + self._make_security_group('json', 'meh', 'meh')['security_group'] # As the security group create operation also creates 2 security group # rules there is no need to explicitly create any rule - self.ctx.project_id = self._project_id - self._list('security-group-rules', neutron_context=self.ctx) + self._list('security-group-rules', as_admin=True) self._verify_dirty_bit('security_group_rule', expected_value=False) diff --git a/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py b/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py index 2957a189bf..db41501ef9 100644 --- a/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py +++ b/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py @@ -209,13 +209,13 @@ class L3SchedulerBaseMixin(object): @contextlib.contextmanager def router_with_ext_gw(self, name='router1', admin_state_up=True, - fmt=None, tenant_id=uuidutils.generate_uuid(), + fmt=None, tenant_id=None, external_gateway_info=None, - subnet=None, set_context=False, - **kwargs): + subnet=None, **kwargs): + tenant_id = tenant_id or self._tenant_id router = self._make_router(fmt or self.fmt, tenant_id, name, admin_state_up, external_gateway_info, - set_context, **kwargs) + **kwargs) self._add_external_gateway_to_router( router['router']['id'], subnet['subnet']['network_id']) @@ -1380,6 +1380,7 @@ class L3DvrSchedulerTestCase(L3SchedulerBaseMixin, subnet_ids = [] subnet_ids.append(subnet['subnet']['id']) with self.port(subnet=subnet, + is_admin=True, device_owner=DEVICE_OWNER_COMPUTE, arg_list=('admin_state_up', portbindings.PROFILE,), **host_args): diff --git a/neutron/tests/unit/services/logapi/drivers/ovn/test_driver.py b/neutron/tests/unit/services/logapi/drivers/ovn/test_driver.py index 35c2ec5765..4f4cd7a7ba 100644 --- a/neutron/tests/unit/services/logapi/drivers/ovn/test_driver.py +++ b/neutron/tests/unit/services/logapi/drivers/ovn/test_driver.py @@ -29,7 +29,7 @@ FAKE_CFG_RATE = 123 FAKE_CFG_BURST = 321 -class TestOVNDriver(base.BaseTestCase): +class TestOVNDriverBase(base.BaseTestCase): def setUp(self): super().setUp() @@ -91,6 +91,8 @@ class TestOVNDriver(base.BaseTestCase): meter_band_obj_dict = {**meter_band_defaults_dict, **kwargs} return mock.Mock(**meter_band_obj_dict) + +class TestOVNDriver(TestOVNDriverBase): def test_create(self): driver = self._log_driver self.assertEqual(self.log_plugin, driver._log_plugin) @@ -106,62 +108,6 @@ class TestOVNDriver(base.BaseTestCase): driver2 = self._log_driver_reinit() self.assertEqual(test_log_base, driver2.meter_name) - def test__create_ovn_fair_meter(self): - mock_find_rows = mock.Mock() - mock_find_rows.execute.return_value = None - self._nb_ovn.db_find_rows.return_value = mock_find_rows - self._log_driver._create_ovn_fair_meter(self._nb_ovn.transaction) - self.assertFalse(self._nb_ovn.meter_del.called) - self.assertTrue(self._nb_ovn.meter_add.called) - self.assertFalse( - self._nb_ovn.transaction.return_value.__enter__.called) - self._nb_ovn.meter_add.assert_called_once_with( - name="acl_log_meter", - unit="pktps", - rate=FAKE_CFG_RATE, - fair=True, - burst_size=FAKE_CFG_BURST, - may_exist=False, - external_ids={ovn_const.OVN_DEVICE_OWNER_EXT_ID_KEY: - log_const.LOGGING_PLUGIN}) - - def test__create_ovn_fair_meter_unchanged(self): - mock_find_rows = mock.Mock() - mock_find_rows.execute.return_value = [self._fake_meter()] - self._nb_ovn.db_find_rows.return_value = mock_find_rows - self._nb_ovn.lookup.side_effect = lambda table, key: ( - self._fake_meter_band() if key == "test_band" else None) - self._log_driver._create_ovn_fair_meter(self._nb_ovn.transaction) - self.assertFalse(self._nb_ovn.meter_del.called) - self.assertFalse(self._nb_ovn.meter_add.called) - - def test__create_ovn_fair_meter_changed(self): - mock_find_rows = mock.Mock() - mock_find_rows.execute.return_value = [self._fake_meter(fair=[False])] - self._nb_ovn.db_find_rows.return_value = mock_find_rows - self._nb_ovn.lookup.return_value = self._fake_meter_band() - self._log_driver._create_ovn_fair_meter(self._nb_ovn.transaction) - self.assertTrue(self._nb_ovn.meter_del.called) - self.assertTrue(self._nb_ovn.meter_add.called) - - def test__create_ovn_fair_meter_band_changed(self): - mock_find_rows = mock.Mock() - mock_find_rows.execute.return_value = [self._fake_meter()] - self._nb_ovn.db_find_rows.return_value = mock_find_rows - self._nb_ovn.lookup.return_value = self._fake_meter_band(rate=666) - self._log_driver._create_ovn_fair_meter(self._nb_ovn.transaction) - self.assertTrue(self._nb_ovn.meter_del.called) - self.assertTrue(self._nb_ovn.meter_add.called) - - def test__create_ovn_fair_meter_band_missing(self): - mock_find_rows = mock.Mock() - mock_find_rows.execute.return_value = [self._fake_meter()] - self._nb_ovn.db_find_rows.return_value = mock_find_rows - self._nb_ovn.lookup.side_effect = idlutils.RowNotFound - self._log_driver._create_ovn_fair_meter(self._nb_ovn.transaction) - self.assertTrue(self._nb_ovn.meter_del.called) - self.assertTrue(self._nb_ovn.meter_add.called) - class _fake_acl(): def __init__(self, name=None, **acl_dict): acl_defaults_dict = { diff --git a/neutron/tests/unit/services/metering/test_metering_plugin.py b/neutron/tests/unit/services/metering/test_metering_plugin.py index 87a593bcf9..33961a20c6 100644 --- a/neutron/tests/unit/services/metering/test_metering_plugin.py +++ b/neutron/tests/unit/services/metering/test_metering_plugin.py @@ -17,7 +17,6 @@ from unittest import mock from neutron_lib.agent import topics from neutron_lib.api.definitions import metering as metering_apidef from neutron_lib import context -from neutron_lib.db import api as db_api from neutron_lib.plugins import constants from neutron_lib.plugins import directory from neutron_lib.tests import tools @@ -60,20 +59,6 @@ class MeteringTestExtensionManager(object): return [] -# TODO(akamyshnikova):we need this temporary FakeContext class while Context -# checking for existence of session attribute. -class FakeContext(context.ContextBaseWithSession): - def __init__(self, *args, **kwargs): - super(FakeContext, self).__init__(*args, **kwargs) - self._session = None - - @property - def session(self): - if self._session is None: - self._session = db_api.get_writer_session() - return self._session - - class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, test_l3.L3NatTestCaseMixin, test_metering_db.MeteringPluginDbTestCaseMixin): @@ -97,11 +82,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, self.uuid_patch = mock.patch(uuid, return_value=self.uuid) self.mock_uuid = self.uuid_patch.start() - self.project_id = 'a7e61382-47b8-4d40-bae3-f95981b5637b' - self.ctx = FakeContext('', self.project_id, is_admin=True) - self.context_patch = mock.patch('neutron_lib.context.Context', - return_value=self.ctx) - self.mock_context = self.context_patch.start() + self.ctx = context.Context('', self._tenant_id).elevated() self.topic = topics.METERING_AGENT @@ -159,7 +140,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'gw_port_id': None, 'admin_state_up': True, 'distributed': False, - 'project_id': self.project_id, + 'project_id': self._tenant_id, '_metering_labels': [ {'rules': [], 'id': self.uuid, 'shared': False, @@ -171,11 +152,9 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, with self.router(name='router2', tenant_id=tenant_id_2, set_context=True): self.mock_uuid.return_value = self.uuid - with self.router(name='router1', tenant_id=self.project_id, - set_context=True): - with self.metering_label(tenant_id=self.project_id, - set_context=True): - self.mock_add.assert_called_with(self.ctx, expected) + with self.router(name='router1'): + with self.metering_label(): + self.mock_add.assert_called_with(mock.ANY, expected) def test_add_metering_label_shared_rpc_call(self): second_uuid = 'e27fe2df-376e-4ac7-ae13-92f050a21f84' @@ -184,7 +163,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'gw_port_id': None, 'admin_state_up': True, 'distributed': False, - 'project_id': self.project_id, + 'project_id': self._tenant_id, '_metering_labels': [ {'rules': [], 'id': self.uuid, 'shared': False, @@ -195,14 +174,11 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'id': self.uuid}] tenant_id_2 = '8a268a58-1610-4890-87e0-07abb8231206' - with self.router(name='router1', tenant_id=self.project_id, - shared=True, set_context=True): - with self.metering_label(tenant_id=self.project_id, - set_context=True): + with self.router(name='router1', shared=True): + with self.metering_label(): self.mock_uuid.return_value = second_uuid - with self.metering_label(tenant_id=tenant_id_2, shared=True, - set_context=True): - self.mock_add.assert_called_with(self.ctx, expected) + with self.metering_label(tenant_id=tenant_id_2, shared=True): + self.mock_add.assert_called_with(mock.ANY, expected) def test_remove_metering_label_rpc_call(self): expected = [{'status': 'ACTIVE', @@ -210,19 +186,19 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'gw_port_id': None, 'admin_state_up': True, 'distributed': False, - 'project_id': self.project_id, + 'project_id': self._tenant_id, '_metering_labels': [ {'rules': [], 'id': self.uuid, 'shared': False, 'name': 'label'}], 'id': self.uuid}] - with self.router(tenant_id=self.project_id, set_context=True): - with self.metering_label(tenant_id=self.project_id, - set_context=True) as label: + with self.router(): + with self.metering_label() as label: self.mock_add.assert_called_with(mock.ANY, expected) self._delete('metering-labels', - label['metering_label']['id']) + label['metering_label']['id'], + as_admin=True) self.mock_remove.assert_called_with(mock.ANY, expected) def test_remove_one_metering_label_rpc_call(self): @@ -232,7 +208,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'gw_port_id': None, 'admin_state_up': True, 'distributed': False, - 'project_id': self.project_id, + 'project_id': self._tenant_id, '_metering_labels': [ {'rules': [], 'id': self.uuid, 'shared': False, @@ -246,22 +222,21 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'gw_port_id': None, 'admin_state_up': True, 'distributed': False, - 'project_id': self.project_id, + 'project_id': self._tenant_id, '_metering_labels': [ {'rules': [], 'id': second_uuid, 'shared': False, 'name': 'label'}], 'id': self.uuid}] - with self.router(tenant_id=self.project_id, set_context=True): - with self.metering_label(tenant_id=self.project_id, - set_context=True): + with self.router(): + with self.metering_label(): self.mock_uuid.return_value = second_uuid - with self.metering_label(tenant_id=self.project_id, - set_context=True) as label: + with self.metering_label() as label: self.mock_add.assert_called_with(mock.ANY, expected_add) self._delete('metering-labels', - label['metering_label']['id']) + label['metering_label']['id'], + as_admin=True) self.mock_remove.assert_called_with(mock.ANY, expected_remove) def test_add_and_remove_metering_label_rule_rpc_call(self): @@ -271,7 +246,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'gw_port_id': None, 'admin_state_up': True, 'distributed': False, - 'project_id': self.project_id, + 'project_id': self._tenant_id, '_metering_labels': [ {'rule': { 'remote_ip_prefix': @@ -291,7 +266,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'gw_port_id': None, 'admin_state_up': True, 'distributed': False, - 'project_id': self.project_id, + 'project_id': self._tenant_id, '_metering_labels': [ {'rule': { 'remote_ip_prefix': @@ -307,15 +282,15 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'id': self.uuid}] remote_ip_prefix = {'remote_ip_prefix': '10.0.0.0/24'} - with self.router(tenant_id=self.project_id, set_context=True): - with self.metering_label(tenant_id=self.project_id, - set_context=True) as label: + with self.router(): + with self.metering_label() as label: la = label['metering_label'] self.mock_uuid.return_value = second_uuid with self.metering_label_rule(la['id'], **remote_ip_prefix): self.mock_add_rule.assert_called_with(mock.ANY, expected_add) - self._delete('metering-label-rules', second_uuid) + self._delete('metering-label-rules', second_uuid, + as_admin=True) self.mock_remove_rule.assert_called_with(mock.ANY, expected_del) @@ -326,7 +301,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'gw_port_id': None, 'admin_state_up': True, 'distributed': False, - 'project_id': self.project_id, + 'project_id': self._tenant_id, '_metering_labels': [ {'rule': { 'source_ip_prefix': @@ -346,7 +321,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'gw_port_id': None, 'admin_state_up': True, 'distributed': False, - 'project_id': self.project_id, + 'project_id': self._tenant_id, '_metering_labels': [ {'rule': { 'source_ip_prefix': @@ -362,16 +337,16 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'id': self.uuid}] source_ip_prefix = {'source_ip_prefix': '10.0.0.0/24'} - with self.router(tenant_id=self.project_id, set_context=True): - with self.metering_label(tenant_id=self.project_id, - set_context=True) as label: + with self.router(): + with self.metering_label() as label: la = label['metering_label'] self.mock_uuid.return_value = second_uuid with self.metering_label_rule(la['id'], **source_ip_prefix): self.mock_add_rule.assert_called_with(mock.ANY, expected_add) - self._delete('metering-label-rules', second_uuid) + self._delete('metering-label-rules', second_uuid, + as_admin=True) self.mock_remove_rule.assert_called_with(mock.ANY, expected_del) @@ -382,7 +357,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'gw_port_id': None, 'admin_state_up': True, 'distributed': False, - 'project_id': self.project_id, + 'project_id': self._tenant_id, '_metering_labels': [ {'rule': { 'destination_ip_prefix': @@ -402,7 +377,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'gw_port_id': None, 'admin_state_up': True, 'distributed': False, - 'project_id': self.project_id, + 'project_id': self._tenant_id, '_metering_labels': [ {'rule': { 'destination_ip_prefix': @@ -418,16 +393,16 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'id': self.uuid}] source_ip_prefix = {'destination_ip_prefix': '10.0.0.0/24'} - with self.router(tenant_id=self.project_id, set_context=True): - with self.metering_label(tenant_id=self.project_id, - set_context=True) as label: + with self.router(): + with self.metering_label() as label: la = label['metering_label'] self.mock_uuid.return_value = second_uuid with self.metering_label_rule(la['id'], **source_ip_prefix): self.mock_add_rule.assert_called_with(mock.ANY, expected_add) - self._delete('metering-label-rules', second_uuid) + self._delete('metering-label-rules', second_uuid, + as_admin=True) self.mock_remove_rule.assert_called_with(mock.ANY, expected_del) @@ -438,7 +413,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'gw_port_id': None, 'admin_state_up': True, 'distributed': False, - 'project_id': self.project_id, + 'project_id': self._tenant_id, '_metering_labels': [ {'rule': { 'destination_ip_prefix': @@ -459,7 +434,7 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, 'gw_port_id': None, 'admin_state_up': True, 'distributed': False, - 'project_id': self.project_id, + 'project_id': self._tenant_id, '_metering_labels': [ {'rule': { 'destination_ip_prefix': @@ -477,23 +452,22 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, ip_prefixes = {'source_ip_prefix': '10.0.0.0/24', 'destination_ip_prefix': '0.0.0.0/0'} - with self.router(tenant_id=self.project_id, set_context=True): - with self.metering_label(tenant_id=self.project_id, - set_context=True) as label: + with self.router(): + with self.metering_label() as label: la = label['metering_label'] self.mock_uuid.return_value = second_uuid with self.metering_label_rule(la['id'], **ip_prefixes): self.mock_add_rule.assert_called_with(mock.ANY, expected_add) - self._delete('metering-label-rules', second_uuid) + self._delete('metering-label-rules', second_uuid, + as_admin=True) self.mock_remove_rule.assert_called_with(mock.ANY, expected_del) def test_add_and_remove_metering_label_rule_src_and_remote_ip(self): - with self.router(tenant_id=self.project_id, set_context=True): - with self.metering_label(tenant_id=self.project_id, - set_context=True) as label: + with self.router(): + with self.metering_label() as label: la = label['metering_label'] res = self._create_metering_label_rule( @@ -514,9 +488,8 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, "NeutronError"]["message"]) def test_add_and_remove_metering_label_rule_dest_and_remote_ip(self): - with self.router(tenant_id=self.project_id, set_context=True): - with self.metering_label(tenant_id=self.project_id, - set_context=True) as label: + with self.router(): + with self.metering_label() as label: la = label['metering_label'] res = self._create_metering_label_rule( @@ -537,9 +510,8 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, "NeutronError"]["message"]) def test_add_and_remove_metering_label_rule_no_ip_prefix_entered(self): - with self.router(tenant_id=self.project_id, set_context=True): - with self.metering_label(tenant_id=self.project_id, - set_context=True) as label: + with self.router(): + with self.metering_label() as label: la = label['metering_label'] res = self._create_metering_label_rule( @@ -567,12 +539,15 @@ class TestMeteringPlugin(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, # 1b9e9a6c2ccf7f9bc06429f53e5126f356ae3d4a/neutron/api/v2/base.py#L563 self.ctx.GUARD_TRANSACTION = False with self.metering_label(tenant_id=tenant_id) as metering_label: - with self.router(tenant_id=tenant_id, set_context=True) as r: - router = self._show('routers', r['router']['id']) + with self.router(tenant_id=tenant_id) as r: + router = self._show('routers', r['router']['id'], + tenant_id=tenant_id) self.assertEqual(tenant_id, router['router']['tenant_id']) metering_label_id = metering_label['metering_label']['id'] - self._delete('metering-labels', metering_label_id, 204) - router = self._show('routers', r['router']['id']) + self._delete('metering-labels', metering_label_id, 204, + as_admin=True) + router = self._show('routers', r['router']['id'], + tenant_id=tenant_id) self.assertEqual(tenant_id, router['router']['tenant_id']) @@ -609,11 +584,7 @@ class TestMeteringPluginL3AgentScheduler( self.uuid_patch = mock.patch(uuid, return_value=self.uuid) self.mock_uuid = self.uuid_patch.start() - self.project_id = 'a7e61382-47b8-4d40-bae3-f95981b5637b' - self.ctx = FakeContext('', self.project_id, is_admin=True) - self.context_patch = mock.patch('neutron_lib.context.Context', - return_value=self.ctx) - self.mock_context = self.context_patch.start() + self.ctx = context.Context('', self._tenant_id).elevated() self.l3routers_patch = mock.patch(scheduler + '.get_l3_agents_hosting_routers') @@ -640,7 +611,7 @@ class TestMeteringPluginL3AgentScheduler( 'gw_port_id': None, 'admin_state_up': True, 'distributed': False, - 'project_id': self.project_id, + 'project_id': self._tenant_id, '_metering_labels': [ {'rules': [], 'id': second_uuid, 'shared': False, @@ -651,7 +622,7 @@ class TestMeteringPluginL3AgentScheduler( 'gw_port_id': None, 'admin_state_up': True, 'distributed': False, - 'project_id': self.project_id, + 'project_id': self._tenant_id, '_metering_labels': [ {'rules': [], 'id': second_uuid, 'shared': False, @@ -670,15 +641,12 @@ class TestMeteringPluginL3AgentScheduler( self.l3routers_mock.side_effect = side_effect - with self.router(name='router1', tenant_id=self.project_id, - set_context=True): + with self.router(name='router1'): self.mock_uuid.return_value = second_uuid - with self.router(name='router2', tenant_id=self.project_id, - set_context=True): - with self.metering_label(tenant_id=self.project_id, - set_context=True): + with self.router(name='router2'): + with self.metering_label(): self.mock_add.assert_called_with( - self.ctx, tools.UnorderedList(expected)) + mock.ANY, tools.UnorderedList(expected)) class TestMeteringPluginL3AgentSchedulerServicePlugin( @@ -727,7 +695,6 @@ class TestMeteringPluginRpcFromL3Agent( self.meter_plugin = directory.get_plugin(constants.METERING) - self.tenant_id = 'admin_tenant_id' self.tenant_id_1 = 'tenant_id_1' self.tenant_id_2 = 'tenant_id_2' @@ -759,8 +726,7 @@ class TestMeteringPluginRpcFromL3Agent( def test_get_sync_data_metering_shared(self): with self.router(name='router1', tenant_id=self.tenant_id_1): with self.router(name='router2', tenant_id=self.tenant_id_2): - with self.metering_label(tenant_id=self.tenant_id, - shared=True): + with self.metering_label(shared=True): callbacks = metering_rpc.MeteringRpcCallbacks( self.meter_plugin) data = callbacks.get_sync_data_metering(self.adminContext) @@ -773,7 +739,7 @@ class TestMeteringPluginRpcFromL3Agent( def test_get_sync_data_metering_not_shared(self): with self.router(name='router1', tenant_id=self.tenant_id_1): with self.router(name='router2', tenant_id=self.tenant_id_2): - with self.metering_label(tenant_id=self.tenant_id): + with self.metering_label(): callbacks = metering_rpc.MeteringRpcCallbacks( self.meter_plugin) data = callbacks.get_sync_data_metering(self.adminContext) @@ -786,13 +752,11 @@ class TestMeteringPluginRpcFromL3Agent( with self.subnet() as subnet: s = subnet['subnet'] self._set_net_external(s['network_id']) - with self.router( - name='router1', tenant_id=self.tenant_id - ) as router1: + with self.router(name='router1') as router1: self._add_external_gateway_to_router( router1['router']['id'], s['network_id']) - with self.router(name='router2', tenant_id=self.tenant_id): - with self.metering_label(tenant_id=self.tenant_id): + with self.router(name='router2'): + with self.metering_label(): callbacks = metering_rpc.MeteringRpcCallbacks( self.meter_plugin) data = callbacks.get_sync_data_metering( @@ -807,18 +771,15 @@ class TestMeteringPluginRpcFromL3Agent( with self.subnet() as subnet: s = subnet['subnet'] self._set_net_external(s['network_id']) - with self.router( - name='router1', tenant_id=self.tenant_id - ) as router1: + with self.router(name='router1') as router1: self._add_external_gateway_to_router( router1['router']['id'], s['network_id']) with self.router( - name='router2', tenant_id=self.tenant_id, - admin_state_up=False + name='router2', admin_state_up=False ) as router2: self._add_external_gateway_to_router( router2['router']['id'], s['network_id']) - with self.metering_label(tenant_id=self.tenant_id): + with self.metering_label(): callbacks = metering_rpc.MeteringRpcCallbacks( self.meter_plugin) data = callbacks.get_sync_data_metering( diff --git a/neutron/tests/unit/services/ovn_l3/test_plugin.py b/neutron/tests/unit/services/ovn_l3/test_plugin.py index 29a81f22d7..a4f1512555 100644 --- a/neutron/tests/unit/services/ovn_l3/test_plugin.py +++ b/neutron/tests/unit/services/ovn_l3/test_plugin.py @@ -434,8 +434,6 @@ class TestOVNL3RouterPlugin(test_mech_driver.Ml2PluginV2TestCase): {'router': updated_data}) self.l3_inst._nb_ovn.update_lrouter.assert_called_once_with( 'neutron-router-id', enabled=True, external_ids={ - ovn_const.OVN_GW_PORT_EXT_ID_KEY: '', - ovn_const.OVN_GW_NETWORK_EXT_ID_KEY: '', ovn_const.OVN_REV_NUM_EXT_ID_KEY: '1', ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: 'router', ovn_const.OVN_AZ_HINTS_EXT_ID_KEY: ''}) @@ -456,8 +454,6 @@ class TestOVNL3RouterPlugin(test_mech_driver.Ml2PluginV2TestCase): 'neutron-router-id', enabled=False, external_ids={ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: 'test', ovn_const.OVN_REV_NUM_EXT_ID_KEY: '1', - ovn_const.OVN_GW_PORT_EXT_ID_KEY: '', - ovn_const.OVN_GW_NETWORK_EXT_ID_KEY: '', ovn_const.OVN_AZ_HINTS_EXT_ID_KEY: ''}) @mock.patch.object(utils, 'get_lrouter_non_gw_routes') @@ -551,8 +547,6 @@ class TestOVNL3RouterPlugin(test_mech_driver.Ml2PluginV2TestCase): external_ids = {ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: 'router', ovn_const.OVN_REV_NUM_EXT_ID_KEY: '1', - ovn_const.OVN_GW_PORT_EXT_ID_KEY: 'gw-port-id', - ovn_const.OVN_GW_NETWORK_EXT_ID_KEY: 'ext-network-id', ovn_const.OVN_AZ_HINTS_EXT_ID_KEY: ''} self.l3_inst._nb_ovn.create_lrouter.assert_called_once_with( 'neutron-router-id', external_ids=external_ids, diff --git a/neutron/tests/unit/services/qos/test_qos_plugin.py b/neutron/tests/unit/services/qos/test_qos_plugin.py index 875712f172..ecdea9987f 100644 --- a/neutron/tests/unit/services/qos/test_qos_plugin.py +++ b/neutron/tests/unit/services/qos/test_qos_plugin.py @@ -1927,7 +1927,8 @@ class TestQoSRuleAlias(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): data = {'alias_%s_rule' % rule_type: kwargs} resource = '%s/alias-%s-rules' % (qos.ALIAS, rule_type.replace('_', '-')) - request = self.new_update_request(resource, data, rule_id, self.fmt) + request = self.new_update_request(resource, data, rule_id, self.fmt, + as_admin=True) res = request.get_response(self.ext_api) if res.status_int >= webob.exc.HTTPClientError.code: raise webob.exc.HTTPClientError(code=res.status_int) @@ -1936,7 +1937,8 @@ class TestQoSRuleAlias(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): def _show_rule(self, rule_type, rule_id): resource = '%s/alias-%s-rules' % (qos.ALIAS, rule_type.replace('_', '-')) - request = self.new_show_request(resource, rule_id, self.fmt) + request = self.new_show_request(resource, rule_id, self.fmt, + as_admin=True) res = request.get_response(self.ext_api) if res.status_int >= webob.exc.HTTPClientError.code: raise webob.exc.HTTPClientError(code=res.status_int) @@ -1945,7 +1947,8 @@ class TestQoSRuleAlias(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): def _delete_rule(self, rule_type, rule_id): resource = '%s/alias-%s-rules' % (qos.ALIAS, rule_type.replace('_', '-')) - request = self.new_delete_request(resource, rule_id, self.fmt) + request = self.new_delete_request(resource, rule_id, self.fmt, + as_admin=True) res = request.get_response(self.ext_api) if res.status_int >= webob.exc.HTTPClientError.code: raise webob.exc.HTTPClientError(code=res.status_int) @@ -2014,7 +2017,8 @@ class TestQoSRuleAlias(test_db_base_plugin_v2.NeutronDbPluginV2TestCase): return_value=None): resource = '%s/alias-%s-rules' % (qos.ALIAS, rule_type.replace('_', '-')) - request = self.new_show_request(resource, rule_id, self.fmt) + request = self.new_show_request(resource, rule_id, self.fmt, + as_admin=True) res = request.get_response(self.ext_api) self.assertEqual(webob.exc.HTTPNotFound.code, res.status_int) diff --git a/neutron/tests/unit/services/revisions/test_revision_plugin.py b/neutron/tests/unit/services/revisions/test_revision_plugin.py index 77bd869ae9..8f5ae05916 100644 --- a/neutron/tests/unit/services/revisions/test_revision_plugin.py +++ b/neutron/tests/unit/services/revisions/test_revision_plugin.py @@ -97,7 +97,7 @@ class TestRevisionPlugin(test_plugin.Ml2PluginV2TestCase): # with the flush process that occurs with these two connected objects, # creating two copies of the Network object in the Session and putting # it into an invalid state. - with self.network(shared=True): + with self.network(shared=True, as_admin=True): pass def test_port_name_update_revises(self): @@ -279,7 +279,8 @@ class TestRevisionPlugin(test_plugin.Ml2PluginV2TestCase): 'project_id': uuidutils.generate_uuid()}} qos_obj = qos_plugin.create_policy(self.ctx, qos_policy) data = {'port': {'qos_policy_id': qos_obj['id']}} - response = self._update('ports', port['port']['id'], data) + response = self._update('ports', port['port']['id'], data, + as_admin=True) new_rev = response['port']['revision_number'] self.assertGreater(new_rev, rev) @@ -292,7 +293,8 @@ class TestRevisionPlugin(test_plugin.Ml2PluginV2TestCase): 'project_id': uuidutils.generate_uuid()}} qos_obj = qos_plugin.create_policy(self.ctx, qos_policy) data = {'network': {'qos_policy_id': qos_obj['id']}} - response = self._update('networks', network['network']['id'], data) + response = self._update('networks', network['network']['id'], data, + as_admin=True) new_rev = response['network']['revision_number'] self.assertGreater(new_rev, rev) diff --git a/releasenotes/notes/Deprecate-support-for-Windows-OS-80e32ef7e5e05b44.yaml b/releasenotes/notes/Deprecate-support-for-Windows-OS-80e32ef7e5e05b44.yaml new file mode 100644 index 0000000000..d5a627e8fe --- /dev/null +++ b/releasenotes/notes/Deprecate-support-for-Windows-OS-80e32ef7e5e05b44.yaml @@ -0,0 +1,5 @@ +--- +deprecations: + - | + Support for Neutron on Windows operating systems is deprecated since 2023.2 + release and will be removed in 2024.2. diff --git a/releasenotes/notes/bug-1953165-6e848ea2c0398f56.yaml b/releasenotes/notes/bug-1953165-6e848ea2c0398f56.yaml new file mode 100644 index 0000000000..6c79c0daef --- /dev/null +++ b/releasenotes/notes/bug-1953165-6e848ea2c0398f56.yaml @@ -0,0 +1,16 @@ +--- +issues: + - | + The high availability of metadata service on isolated networks is limited + or non-existent. IPv4 metadata is redundant when the DHCP agent managing + it is redundant, but recovery is tied to the renewal of the DHCP lease, + making most recoveries very slow. IPv6 metadata is not redundant at all + as the IPv6 metadata address can only be configured in a single place at + a time as it is link-local. Multiple agents trying to configure it will + generate an IPv6 duplicate address detection failure. + + Administrators may observe the IPv6 metadata address in "dadfailed" state + in the DHCP namespace for this reason, which is only an indication it is + not highly available. Until a redesign is made to the isolated metadata + service there is not a better deployment option. See `bug 1953165 + <https://bugs.launchpad.net/neutron/+bug/1953165>`_ for information. diff --git a/releasenotes/notes/enable-enforce-scope-and-new-defaults-1f82a9eb71125f5d.yaml b/releasenotes/notes/enable-enforce-scope-and-new-defaults-1f82a9eb71125f5d.yaml new file mode 100644 index 0000000000..5ca899343e --- /dev/null +++ b/releasenotes/notes/enable-enforce-scope-and-new-defaults-1f82a9eb71125f5d.yaml @@ -0,0 +1,25 @@ +--- +upgrade: + - | + The Neutron service enable the API policies (RBAC) new defaults and scope + by default. The Default value of config options + ``[oslo_policy] enforce_scope`` and + ``[oslo_policy] oslo_policy.enforce_new_defaults`` have been changed + to ``True``. + + This means if you are using system scope token to access Neutron API then + the request will be failed with 403 error code. Also, new defaults will be + enforced by default. To know about the new defaults of each policy + rule, refer to the `Policy New Defaults`_. For more detail about + the Neutron API policies changes, refer to `Policy Concepts`_. + + If you want to disable them then modify the below config options value in + ``neutron.conf`` file:: + + [oslo_policy] + enforce_new_defaults=False + enforce_scope=False + + .. _`Policy New Defaults`: https://docs.openstack.org/neutron/latest/configuration/policy.html + .. _`Policy Concepts`: https://docs.openstack.org/neutron/latest/contributor/internals/policy.html + diff --git a/releasenotes/notes/localnet-learn-fdb-22469280b49701fc.yaml b/releasenotes/notes/localnet-learn-fdb-22469280b49701fc.yaml new file mode 100644 index 0000000000..9af9ca48be --- /dev/null +++ b/releasenotes/notes/localnet-learn-fdb-22469280b49701fc.yaml @@ -0,0 +1,23 @@ +--- +issues: + - | + In OVN 22.09 the option "localnet_learn_fdb" was added, enabling localnet + ports to learn MAC addresses and store them at the FDB table. + There is no aging mechanism for those MACs (that is the reason for not + having this option enabled by default) and therefore it needs to be used + with care, specially when provider networks are big. It is recommended to + perform periodic manual cleanups of FDB table, to avoid scalability + issues -- until OVN implements an aging mechanism for this, tracked at + https://bugzilla.redhat.com/show_bug.cgi?id=2179942. +fixes: + - | + By default localnet ports don't learn MAC addresses and therefore they are + not stored in the FDB table at OVN SB DB. This leads to flooding issues + when the destination traffic is an unknown IP by OpenStack. In OVN 22.09 + the option "localnet_learn_fdb" was added, enabling those ports to learn + MAC addresses and store them at the FDB table. Note there is no aging + mechanism for those MACs, thus this is not enabled by default and needs + to be used carefully, specially when provider networks are big, and/or + performing manual cleanup of FDB table over time to avoid scalability + issues, until OVN implements it at + https://bugzilla.redhat.com/show_bug.cgi?id=2179942. diff --git a/releasenotes/notes/mark_ipv6_pd_enabled_as_experimental-c9bfe343a0beb334.yaml b/releasenotes/notes/mark_ipv6_pd_enabled_as_experimental-c9bfe343a0beb334.yaml new file mode 100644 index 0000000000..b340343261 --- /dev/null +++ b/releasenotes/notes/mark_ipv6_pd_enabled_as_experimental-c9bfe343a0beb334.yaml @@ -0,0 +1,7 @@ +--- +deprecations: + - | + "ipv6_pd_enabled" has been marked as deprecated and marked as experimental. + To continue using it, deployers have to set to True the "ipv6_pd_enabled" + option in the "experimental" section of neutron.conf. See + `Dibbler project concluded <https://bugs.launchpad.net/neutron/+bug/1916428>`_. diff --git a/releasenotes/notes/ovn-recreate-metadata-port-76e2c0e651267aa0.yaml b/releasenotes/notes/ovn-recreate-metadata-port-76e2c0e651267aa0.yaml new file mode 100644 index 0000000000..dfe077945b --- /dev/null +++ b/releasenotes/notes/ovn-recreate-metadata-port-76e2c0e651267aa0.yaml @@ -0,0 +1,11 @@ +--- +fixes: + - | + Fix an issue in the OVN driver where network metadata could + become unavailable if the metadata port was ever deleted, even + if accidental. To re-create the port, a user can now disable, + then enable, DHCP for one of the subnets associated with the + network using the Neutron API. This will try and create the + port, similar to what happens in the DHCP agent for ML2/OVS. + For more information, see bug `2015377 + <https://bugs.launchpad.net/ubuntu/+source/neutron/+bug/2015377>`_. diff --git a/releasenotes/notes/remove_neutron_debug-262a139650d71183.yaml b/releasenotes/notes/remove_neutron_debug-262a139650d71183.yaml new file mode 100644 index 0000000000..1e373d35b2 --- /dev/null +++ b/releasenotes/notes/remove_neutron_debug-262a139650d71183.yaml @@ -0,0 +1,6 @@ +--- +deprecations: + - | + The tool neutron-debug is now removed. With removal of the neutron client + shell code this tool is no longer usable. It had been marked for + deprecation since the Newton (9.0) cycle and unmaintained. diff --git a/releasenotes/releasenotes/notes/network_subnet_mtu_validation-c221f22efcfae927.yaml b/releasenotes/releasenotes/notes/network_subnet_mtu_validation-c221f22efcfae927.yaml new file mode 100644 index 0000000000..f30421c61a --- /dev/null +++ b/releasenotes/releasenotes/notes/network_subnet_mtu_validation-c221f22efcfae927.yaml @@ -0,0 +1,22 @@ +--- +fixes: + - | + The Neutron API has been changed to validate network MTU minimums. + A network's MTU is now only valid if it is the minimum value + allowed based on the IP version of the associated subnets, + 68 for IPv4 and 1280 for IPv6. + + This minimum is now enforced in the following ways: + + * When a subnet is associated with a network, validate + the MTU is large enough for the IP version. Not only + would the subnet be unusable if it was allowed, but the + Linux kernel can fail adding addresses and configuring + network settings like the MTU. + + * When a network MTU is changed, validate the MTU is large + enough for any currently associated subnets. Allowing a + smaller MTU would render any existing subnets unusable. + + See bug `1988069 <https://bugs.launchpad.net/neutron/+bug/1988069>`_ + for more information. diff --git a/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po b/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po index 8c413dc5bd..1670ee18a5 100644 --- a/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po +++ b/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po @@ -6,11 +6,11 @@ msgid "" msgstr "" "Project-Id-Version: Neutron Release Notes\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-11 20:30+0000\n" +"POT-Creation-Date: 2023-05-15 17:46+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2023-01-26 10:18+0000\n" +"PO-Revision-Date: 2023-05-08 11:48+0000\n" "Last-Translator: Andi Chandler <andi@gowling.com>\n" "Language-Team: English (United Kingdom)\n" "Language: en_GB\n" @@ -177,6 +177,9 @@ msgstr "15.3.1" msgid "15.3.4" msgstr "15.3.4" +msgid "15.3.4-112" +msgstr "15.3.4-112" + msgid "16.0.0" msgstr "16.0.0" @@ -201,6 +204,9 @@ msgstr "16.4.0" msgid "16.4.1" msgstr "16.4.1" +msgid "16.4.2-131" +msgstr "16.4.2-131" + msgid "17.0.0" msgstr "17.0.0" @@ -225,6 +231,9 @@ msgstr "17.3.0" msgid "17.4.0" msgstr "17.4.0" +msgid "17.4.1-62" +msgstr "17.4.1-62" + msgid "18.0.0" msgstr "18.0.0" @@ -255,15 +264,33 @@ msgstr "19.2.0" msgid "19.3.0" msgstr "19.3.0" +msgid "19.5.0" +msgstr "19.5.0" + +msgid "19.6.0" +msgstr "19.6.0" + +msgid "19.7.0" +msgstr "19.7.0" + msgid "20.0.0" msgstr "20.0.0" msgid "20.2.0" msgstr "20.2.0" +msgid "20.3.0" +msgstr "20.3.0" + +msgid "2023.1 Series Release Notes" +msgstr "2023.1 Series Release Notes" + msgid "21.0.0" msgstr "21.0.0" +msgid "21.1.0" +msgstr "21.1.0" + msgid "7.0.1" msgstr "7.0.1" @@ -454,6 +481,23 @@ msgstr "Yoga Series Release Notes" msgid "Zed Series Release Notes" msgstr "Zed Series Release Notes" +msgid "" +"`1996677 <https://bugs.launchpad.net/neutron/+bug/1996677>`_ When the " +"fixed_ips of metadata port is modified, the ip address of tap device in " +"metadata agent is modified." +msgstr "" +"`1996677 <https://bugs.launchpad.net/neutron/+bug/1996677>`_ When the " +"fixed_ips of metadata port is modified, the ip address of tap device in " +"metadata agent is modified." + +msgid "``--ipv6-ra-mode dhcpv6-stateful --ipv6-address-mode dhcpv6-stateful``" +msgstr "``--ipv6-ra-mode dhcpv6-stateful --ipv6-address-mode dhcpv6-stateful``" + +msgid "" +"``--ipv6-ra-mode dhcpv6-stateless --ipv6-address-mode dhcpv6-stateless``" +msgstr "" +"``--ipv6-ra-mode dhcpv6-stateless --ipv6-address-mode dhcpv6-stateless``" + msgid "``--ipv6-ra-mode slaac --ipv6-address-mode slaac``" msgstr "``--ipv6-ra-mode slaac --ipv6-address-mode slaac``" diff --git a/releasenotes/source/locale/fr/LC_MESSAGES/releasenotes.po b/releasenotes/source/locale/fr/LC_MESSAGES/releasenotes.po deleted file mode 100644 index d5b1f19644..0000000000 --- a/releasenotes/source/locale/fr/LC_MESSAGES/releasenotes.po +++ /dev/null @@ -1,90 +0,0 @@ -# Gérald LONLAS <g.lonlas@gmail.com>, 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: Neutron Release Notes\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-11 20: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-10-22 05:44+0000\n" -"Last-Translator: Gérald LONLAS <g.lonlas@gmail.com>\n" -"Language-Team: French\n" -"Language: fr\n" -"X-Generator: Zanata 4.3.3\n" -"Plural-Forms: nplurals=2; plural=(n > 1)\n" - -msgid "7.0.1" -msgstr "7.0.1" - -msgid "7.0.3" -msgstr "7.0.3" - -msgid "7.0.4" -msgstr "7.0.4" - -msgid "7.1.0" -msgstr "7.1.0" - -msgid "7.2.0" -msgstr "7.2.0" - -msgid "8.0.0" -msgstr "8.0.0" - -msgid "8.1.0" -msgstr "8.1.0" - -msgid "8.2.0" -msgstr "8.2.0" - -msgid "8.3.0" -msgstr "8.3.0" - -msgid "9.0.0" -msgstr "9.0.0" - -msgid "Bug Fixes" -msgstr "Corrections de bugs" - -msgid "Current Series Release Notes" -msgstr "Note de la release actuelle" - -msgid "Deprecation Notes" -msgstr "Notes dépréciées " - -msgid "Known Issues" -msgstr "Problèmes connus" - -msgid "Liberty Series Release Notes" -msgstr "Note de release pour Liberty" - -msgid "Mitaka Series Release Notes" -msgstr "Note de release pour Mitaka" - -msgid "Neutron Release Notes" -msgstr "Note de release de muranopkgcheck" - -msgid "Neutron Release Notes Howto" -msgstr "Note de release Howto pour Neutron" - -msgid "Neutron can interact with keystone v3." -msgstr "Neutron peut interagir avec Keystone version 3" - -msgid "New Features" -msgstr "Nouvelles fonctionnalités" - -msgid "Newton Series Release Notes" -msgstr "Note de release pour Newton" - -msgid "Other Notes" -msgstr "Autres notes" - -msgid "Security Issues" -msgstr "Problèmes de sécurités" - -msgid "Start using reno to manage release notes." -msgstr "Commence à utiliser reno pour la gestion des notes de release" - -msgid "Upgrade Notes" -msgstr "Notes de mises à jours" diff --git a/releasenotes/source/locale/ko_KR/LC_MESSAGES/releasenotes.po b/releasenotes/source/locale/ko_KR/LC_MESSAGES/releasenotes.po deleted file mode 100644 index 50634aafb0..0000000000 --- a/releasenotes/source/locale/ko_KR/LC_MESSAGES/releasenotes.po +++ /dev/null @@ -1,103 +0,0 @@ -# Ian Y. Choi <ianyrchoi@gmail.com>, 2016. #zanata -# jtjang <jang.jitae@gmail.com>, 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: Neutron Release Notes\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-11 20: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-08-06 12:14+0000\n" -"Last-Translator: Ian Y. Choi <ianyrchoi@gmail.com>\n" -"Language-Team: Korean (South Korea)\n" -"Language: ko_KR\n" -"X-Generator: Zanata 4.3.3\n" -"Plural-Forms: nplurals=1; plural=0\n" - -msgid "7.0.1" -msgstr "7.0.1" - -msgid "7.0.3" -msgstr "7.0.3" - -msgid "7.0.4" -msgstr "7.0.4" - -msgid "7.1.0" -msgstr "7.1.0" - -msgid "8.0.0" -msgstr "8.0.0" - -msgid "8.1.0" -msgstr "8.1.0" - -msgid "" -"A DHCP agent is assigned to an availability zone; the network will be hosted " -"by the DHCP agent with availability zone specified by the user." -msgstr "" -"DHCP 에이전트를 가용성 존에 할당합니다. DHCP 에이전트가 사용자에 의해 명시된 " -"가용성 존과 함께 해당 네트워크를 호스트할 것입니다." - -msgid "" -"A new API endpoint /v2.0/network-ip-availabilities that allows an admin to " -"quickly get counts of used_ips and total_ips for network(s) is available. " -"New endpoint allows filtering by network_id, network_name, tenant_id, and " -"ip_version. Response returns network and nested subnet data that includes " -"used and total IPs." -msgstr "" -"관리자가 네트워크에 대해 used_ip 및 total_ip 개수를 빠르게 가져오도록 허용하" -"는 새로운 API 엔드포인트 /v2.0/network-ip-availabilities 를 사용 가능합니다. " -"새로운 엔드포인트는 network_id, network_name, tenant_id, 그리고 ip_version으" -"로 필터링을 할 수 있습니다. 응답은 사용한 그리고 전체 IP를 포함하는 네트워크 " -"및 둘러싸인 서브넷 데이터를 반환합니다." - -msgid "" -"A new rule has been added to the API that allows for tagging traffic with " -"DSCP values. This is currently supported by the Open vSwitch QoS driver." -msgstr "" -"DSCP값과 함께 태깅 트래픽을 허용하는 새로운 규칙이 API에 추가되었다. 이것은 " -"현재 OpenvSwitch QoS 드라이버에 의해 지원된다." - -msgid "API sorting and pagination features are now enabled by default." -msgstr "API 정렬 및 페이징 기능이 이제 기본으로 활성화됩니다." - -msgid "Bug Fixes" -msgstr "버그 수정" - -msgid "Current Series Release Notes" -msgstr "현재 시리즈에 대한 릴리즈 노트" - -msgid "Deprecation Notes" -msgstr "사용하지 않는 기능" - -msgid "Fixes bug 1537734" -msgstr "버그 1537734를 수정합니다" - -msgid "Fixes bug 1572670" -msgstr "버그 1572670를 수정합니다" - -msgid "Known Issues" -msgstr "알려진 이슈" - -msgid "Liberty Series Release Notes" -msgstr "Liberty 시리즈에 대한 릴리즈 노트" - -msgid "Mitaka Series Release Notes" -msgstr "Mitaka 시리즈에 대한 릴리즈 노트" - -msgid "Neutron Release Notes" -msgstr "Neutron 릴리즈 노트" - -msgid "New Features" -msgstr "새로운 기능" - -msgid "Other Notes" -msgstr "기타 기능" - -msgid "Security Issues" -msgstr "보안 이슈" - -msgid "Upgrade Notes" -msgstr "업그레이드 노트" diff --git a/requirements.txt b/requirements.txt index 2b2d62fbb9..73796c43eb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,7 +20,7 @@ Jinja2>=2.10 # BSD License (3 clause) keystonemiddleware>=5.1.0 # Apache-2.0 netaddr>=0.7.18 # BSD netifaces>=0.10.4 # MIT -neutron-lib>=3.4.0 # Apache-2.0 +neutron-lib>=3.5.0 # Apache-2.0 python-neutronclient>=7.8.0 # Apache-2.0 tenacity>=6.0.0 # Apache-2.0 SQLAlchemy>=1.4.23 # MIT @@ -35,7 +35,6 @@ wsgi_scripts = neutron-api = neutron.cmd.eventlet.server:main_api_eventlet console_scripts = neutron-db-manage = neutron.db.migration.cli:main - neutron-debug = neutron.debug.shell:main neutron-dhcp-agent = neutron.cmd.eventlet.agents.dhcp:main neutron-keepalived-state-change = neutron.cmd.keepalived_state_change:main neutron-ipset-cleanup = neutron.cmd.ipset_cleanup:main @@ -125,6 +124,7 @@ neutron.ml2.extension_drivers = tag_ports_during_bulk_creation = neutron.plugins.ml2.extensions.tag_ports_during_bulk_creation:TagPortsDuringBulkCreationExtensionDriver subnet_dns_publish_fixed_ip = neutron.plugins.ml2.extensions.subnet_dns_publish_fixed_ip:SubnetDNSPublishFixedIPExtensionDriver dns_domain_keywords = neutron.plugins.ml2.extensions.dns_domain_keywords:DnsDomainKeywordsExtensionDriver + port_hints = neutron.plugins.ml2.extensions.port_hints:PortHintsExtensionDriver neutron.ipam_drivers = fake = neutron.tests.unit.ipam.fake_driver:FakeDriver internal = neutron.ipam.drivers.neutrondb_ipam.driver:NeutronDbPool diff --git a/zuul.d/base.yaml b/zuul.d/base.yaml index 64301d9990..073ea3218f 100644 --- a/zuul.d/base.yaml +++ b/zuul.d/base.yaml @@ -117,12 +117,14 @@ - job: name: neutron-fullstack-with-uwsgi-with-neutron-lib-master + branches: ^master$ parent: neutron-fullstack-with-uwsgi required-projects: - openstack/neutron-lib - job: name: neutron-fullstack-with-pyroute2-master + branches: ^master$ parent: neutron-fullstack required-projects: - name: github.com/svinota/pyroute2 @@ -142,6 +144,7 @@ - job: name: neutron-functional-with-uwsgi-with-neutron-lib-master + branches: ^master$ parent: neutron-functional-with-uwsgi required-projects: - openstack/neutron-lib @@ -166,12 +169,14 @@ - job: name: neutron-functional-with-pyroute2-master + branches: ^master$ parent: neutron-functional required-projects: - name: github.com/svinota/pyroute2 - job: name: neutron-functional-with-oslo-master + branches: ^master$ parent: neutron-functional description: | This job installs all oslo libraries from source and executes the @@ -212,6 +217,7 @@ - job: name: neutron-functional-with-sqlalchemy-master + branches: ^master$ parent: neutron-functional required-projects: - name: github.com/sqlalchemy/sqlalchemy diff --git a/zuul.d/grenade.yaml b/zuul.d/grenade.yaml index 921726724f..0c35f846c3 100644 --- a/zuul.d/grenade.yaml +++ b/zuul.d/grenade.yaml @@ -293,6 +293,8 @@ zuul_copy_output: '{{ devstack_base_dir }}/data/ovs': 'logs' '{{ devstack_base_dir }}/data/ovn': 'logs' + '/opt/stack/old/logs': 'logs' + '/opt/stack/new/logs': 'logs' extensions_to_txt: db: true devstack_services: diff --git a/zuul.d/job-templates.yaml b/zuul.d/job-templates.yaml index dbea01ec9e..c092cabc4b 100644 --- a/zuul.d/job-templates.yaml +++ b/zuul.d/job-templates.yaml @@ -23,6 +23,9 @@ - ^roles/.*$ - ^rally-jobs/.*$ - ^zuul.d/(?!(job-templates)).*\.yaml + - openstack-tox-py39: # from openstack-python3-jobs template + timeout: 3600 + irrelevant-files: *irrelevant-files - openstack-tox-py310: # from openstack-python3-jobs template timeout: 3600 irrelevant-files: *irrelevant-files @@ -40,6 +43,9 @@ - openstack-tox-py38-arm64: # from openstack-python3-jobs-arm64 template timeout: 4800 irrelevant-files: *irrelevant-files + - openstack-tox-py39-arm64: # from openstack-python3-jobs-arm64 template + timeout: 4800 + irrelevant-files: *irrelevant-files - openstack-tox-py310-arm64: # from openstack-python3-jobs-arm64 template timeout: 4800 irrelevant-files: *irrelevant-files @@ -48,6 +54,9 @@ - openstack-tox-py38: # from openstack-python3-jobs template timeout: 3600 irrelevant-files: *irrelevant-files + - openstack-tox-py39: # from openstack-python3-jobs template + timeout: 3600 + irrelevant-files: *irrelevant-files - openstack-tox-py310: # from openstack-python3-jobs template timeout: 3600 irrelevant-files: *irrelevant-files @@ -56,51 +65,19 @@ name: neutron-experimental-jobs experimental: jobs: - - neutron-functional - - neutron-functional-with-uwsgi-fips - neutron-functional-with-uwsgi-with-neutron-lib-master - - neutron-functional-with-pyroute2-master - - neutron-functional-with-sqlalchemy-master - - neutron-fullstack - - neutron-fullstack-with-uwsgi-fips - neutron-fullstack-with-uwsgi-with-neutron-lib-master - - neutron-fullstack-with-pyroute2-master - - neutron-ovn-grenade-multinode - - neutron-ovn-tempest-with-uwsgi-loki - neutron-ovn-tempest-full-multinode-ovs-master + - neutron-ovn-grenade-multinode - neutron-ovn-tempest-ovs-master - - neutron-ovn-tempest-with-neutron-lib-master - - neutron-ovs-tempest-with-neutron-lib-master - - neutron-ovs-tempest-slow - - neutron-ovn-tempest-slow - - neutron-ovs-tempest-with-os-ken-master - - neutron-ovn-tempest-postgres-full - - neutron-ovn-tempest-mariadb-full - neutron-ovn-tempest-ovs-release - - neutron-ovn-tempest-ipv6-only-ovs-master - - neutron-ovn-tempest-ovs-master-centos-9-stream - - neutron-ovn-tempest-with-sqlalchemy-master - - neutron-ovs-tempest-with-sqlalchemy-master - - neutron-ovs-tempest-fips - - neutron-ovn-tempest-ovs-release-fips - - devstack-tobiko-neutron: - voting: true - - ironic-tempest-ipa-wholedisk-bios-agent_ipmitool-tinyipa - - openstacksdk-functional-devstack-networking - - neutron-linuxbridge-tempest-plugin-scenario-nftables - - neutron-ovs-tempest-plugin-scenario-iptables_hybrid-nftables - - devstack-enforce-scope - - openstack-tox-py39-with-oslo-master: - timeout: 3600 - irrelevant-files: *irrelevant-files - - neutron-functional-with-oslo-master - - neutron-ovs-tempest-with-oslo-master - - neutron-ovn-tempest-ovs-release-with-oslo-master + - neutron-ovs-tempest-with-neutron-lib-master + - neutron-ovn-tempest-with-uwsgi-loki - project-template: name: neutron-periodic-jobs periodic: - jobs: + jobs: &neutron-periodic-jobs # NOTE(ralonsoh): to be removed when "openstack-tox-py311" is defined # and added to "openstack-python3-jobs" template. - tox-py311: @@ -137,6 +114,8 @@ - neutron-functional-with-oslo-master - neutron-ovs-tempest-with-oslo-master - neutron-ovn-tempest-ovs-release-with-oslo-master + experimental: + jobs: *neutron-periodic-jobs - project-template: name: neutron-skip-level-jobs diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml index ec93017b5c..032064e1d1 100644 --- a/zuul.d/project.yaml +++ b/zuul.d/project.yaml @@ -63,8 +63,6 @@ - ^roles/.*functional.*$ - ^playbooks/.*functional.*$ - ^zuul.d/(?!(project)).*\.yaml - - neutron-ovn-tempest-ovs-release-ubuntu-old: - irrelevant-files: *ovn-irrelevant-files gate: jobs: @@ -76,5 +74,3 @@ - neutron-ovn-tempest-ipv6-only-ovs-release - tempest-integrated-networking: irrelevant-files: *ovn-irrelevant-files - - neutron-ovn-tempest-ovs-release-ubuntu-old: - irrelevant-files: *ovn-irrelevant-files diff --git a/zuul.d/tempest-multinode.yaml b/zuul.d/tempest-multinode.yaml index 740570ee59..d86914482a 100644 --- a/zuul.d/tempest-multinode.yaml +++ b/zuul.d/tempest-multinode.yaml @@ -528,6 +528,7 @@ # TODO(slaweq): propose job with ovs-release and move -master one to # experimental queue name: neutron-ovn-tempest-full-multinode-ovs-master + branches: ^master$ parent: neutron-ovn-multinode-base run: playbooks/multinode-devstack-custom.yaml vars: diff --git a/zuul.d/tempest-singlenode.yaml b/zuul.d/tempest-singlenode.yaml index 1fa3e5b716..6c191e60b0 100644 --- a/zuul.d/tempest-singlenode.yaml +++ b/zuul.d/tempest-singlenode.yaml @@ -295,6 +295,7 @@ - job: name: neutron-ovs-tempest-with-os-ken-master + branches: ^master$ parent: neutron-ovs-tempest-base timeout: 10800 required-projects: @@ -343,6 +344,7 @@ - job: name: neutron-ovn-tempest-with-neutron-lib-master + branches: ^master$ parent: tempest-integrated-networking timeout: 10800 required-projects: @@ -373,12 +375,14 @@ - job: name: neutron-ovs-tempest-with-neutron-lib-master + branches: ^master$ parent: neutron-ovs-tempest-base required-projects: - openstack/neutron-lib - job: name: neutron-ovs-tempest-with-oslo-master + branches: ^master$ parent: neutron-ovs-tempest-base description: | Job testing for devstack/tempest testing Neutron with OVS driver. @@ -420,7 +424,9 @@ timeout: 10800 vars: devstack_localrc: - NEUTRON_DEPLOY_MOD_WSGI: true + # TODO(ykarel) can be enabled once + # https://bugs.launchpad.net/neutron/+bug/1912359 fixed + NEUTRON_DEPLOY_MOD_WSGI: false MYSQL_REDUCE_MEMORY: true devstack_plugins: neutron: https://opendev.org/openstack/neutron.git @@ -468,7 +474,7 @@ - job: name: neutron-ovn-tempest-with-uwsgi-loki - parent: neutron-tempest-with-uwsgi + parent: neutron-ovn-tempest-with-uwsgi timeout: 10800 vars: devstack_services: @@ -615,13 +621,8 @@ parent: neutron-ovn-base - job: - name: neutron-ovn-tempest-ovs-release-ubuntu-old - description: Job testing for devstack/tempest testing Neutron with ovn driver and previously supported (old) version of the Ubuntu operating system - parent: neutron-ovn-base - nodeset: openstack-single-node-focal - -- job: name: neutron-ovn-tempest-ovs-master + branches: ^master$ description: Job testing for devstack/tempest testing Neutron with ovn driver and OVN master branch parent: neutron-ovn-base vars: @@ -634,6 +635,7 @@ - job: name: neutron-ovn-tempest-ovs-release-with-oslo-master + branches: ^master$ description: | Job testing for devstack/tempest testing Neutron with OVN driver. This job installs all oslo libraries from source. @@ -768,6 +770,7 @@ - job: name: neutron-ovn-tempest-ipv6-only-ovs-master + branches: ^master$ parent: neutron-ovn-tempest-ipv6-only-base vars: devstack_localrc: @@ -779,6 +782,7 @@ - job: name: neutron-ovn-tempest-with-sqlalchemy-master + branches: ^master$ parent: tempest-integrated-networking timeout: 10800 required-projects: @@ -814,6 +818,7 @@ - job: name: neutron-ovs-tempest-with-sqlalchemy-master + branches: ^master$ parent: neutron-ovs-tempest-base required-projects: - name: github.com/sqlalchemy/sqlalchemy |
