From 4c207ae082427adf642860f25a789b2bc8951bfd Mon Sep 17 00:00:00 2001 From: Andrey Kurilin Date: Tue, 28 Apr 2020 15:12:31 +0300 Subject: [PATCH] Use NeutronService helper instead of network wrapper This change allows to use network context without admin user Change-Id: Ia25148e08e33d80ea9d021d5e16f87153b902d94 --- .zuul.d/zuul.yaml | 6 + CHANGELOG.rst | 7 + rally-jobs/basic-with-existing-users.yaml | 27 +- rally-jobs/neutron.yaml | 17 +- rally-jobs/rally-mos.yaml | 859 ------------------ rally_openstack/common/osclients.py | 2 +- .../common/services/network/neutron.py | 44 +- rally_openstack/common/wrappers/network.py | 7 +- .../task/contexts/keystone/users.py | 108 ++- .../task/contexts/network/allow_ssh.py | 138 ++- .../task/contexts/network/networks.py | 86 +- .../task/scenarios/neutron/network.py | 428 ++++++--- .../task/scenarios/neutron/utils.py | 25 + .../task/scenarios/nova/servers.py | 15 +- rally_openstack/task/scenarios/vm/utils.py | 20 +- .../verification/tempest/context.py | 33 +- .../neutron/create-and-update-networks.json | 6 +- .../neutron/create-and-update-networks.yaml | 2 - .../neutron/create-and-update-ports.json | 5 +- .../neutron/create-and-update-ports.yaml | 3 - .../neutron/create-and-update-routers.json | 6 +- .../neutron/create-and-update-routers.yaml | 4 - .../neutron/create-and-update-subnets.json | 5 +- .../neutron/create-and-update-subnets.yaml | 3 - tasks/openstack/scenario/neutron.yaml | 4 - tests/ci/cover.sh | 2 +- tests/unit/common/wrappers/test_network.py | 7 +- .../unit/task/contexts/keystone/test_users.py | 118 +-- .../task/contexts/network/test_allow_ssh.py | 158 ++-- .../task/contexts/network/test_network.py | 178 ++-- .../task/scenarios/neutron/test_network.py | 847 ++++++++++------- .../unit/task/scenarios/neutron/test_utils.py | 2 + .../unit/task/scenarios/nova/test_servers.py | 41 +- tests/unit/task/scenarios/vm/test_utils.py | 33 +- .../unit/verification/tempest/test_context.py | 34 +- 35 files changed, 1430 insertions(+), 1850 deletions(-) delete mode 100644 rally-jobs/rally-mos.yaml diff --git a/.zuul.d/zuul.yaml b/.zuul.d/zuul.yaml index 45fdafc5..05c7f1d8 100644 --- a/.zuul.d/zuul.yaml +++ b/.zuul.d/zuul.yaml @@ -58,6 +58,9 @@ - .zuul.d/zuul.yaml - rally-jobs/neutron-trunk.yaml - rally_openstack/common/osclients.py + - rally_openstack/common/services/network + - rally_openstack/task/cleanup/resources.py + - rally_openstack/task/contexts/network - rally_openstack/task/scenarios/neutron/trunk.py - rally_openstack/task/scenarios/neutron/network.py - tests/ci/playbooks @@ -105,6 +108,9 @@ files: - rally-jobs/neutron-trunk.yaml - rally_openstack/common/osclients.py + - rally_openstack/common/services/network + - rally_openstack/task/cleanup/resources.py + - rally_openstack/task/contexts/network - rally_openstack/task/scenarios/neutron/trunk.py - rally_openstack/task/scenarios/neutron/network.py - tests/ci/playbooks diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3bb7fe89..af550898 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -26,9 +26,16 @@ Changed image changed from /rally/xrally_opentstack to /rally/xrally_openstack (there was a typo in work openstack) +* *network@openstack* context does not require admin credentials anymore and + work with regular users as well + Fixed ~~~~~ +* Some neutron scenarios accepted *name* parameter for create or update actions + on various entities. The value of the parameter was always ignored, but + anyway it gave wrong assumption. + * [verification component] Make config parser case sensitivity in TempestContext and TempestConfigfileManager. diff --git a/rally-jobs/basic-with-existing-users.yaml b/rally-jobs/basic-with-existing-users.yaml index fcc04a4f..271a7032 100644 --- a/rally-jobs/basic-with-existing-users.yaml +++ b/rally-jobs/basic-with-existing-users.yaml @@ -78,8 +78,7 @@ workloads: - scenario: - NeutronNetworks.create_and_list_networks: - network_create_args: + NeutronNetworks.create_and_list_networks: {} runner: constant: times: 2 @@ -92,6 +91,8 @@ NeutronNetworks.create_and_list_subnets: subnet_cidr_start: "1.1.0.0/30" subnets_per_network: 2 + contexts: + network: {} runner: constant: times: 2 @@ -111,3 +112,25 @@ sla: failure_rate: max: 0 + + - title: Test VMTask scenario + workloads: + - + scenario: + VMTasks.dd_load_test: + flavor: + name: "m1.tiny" + image: + name: {{image_name}} + floating_network: "public" + force_delete: false + username: "cirros" + contexts: + network: {} + runner: + constant: + times: 2 + concurrency: 2 + sla: + failure_rate: + max: 0 diff --git a/rally-jobs/neutron.yaml b/rally-jobs/neutron.yaml index 6c69d647..b43e33b1 100644 --- a/rally-jobs/neutron.yaml +++ b/rally-jobs/neutron.yaml @@ -89,8 +89,8 @@ NeutronNetworks.create_and_list_subnets: - args: - network_create_args: - subnet_create_args: + network_create_args: {} + subnet_create_args: {} subnet_cidr_start: "1.1.0.0/30" subnets_per_network: 2 runner: @@ -113,8 +113,6 @@ NeutronNetworks.create_and_show_subnets: - args: - network_create_args: - subnet_create_args: subnet_cidr_start: "1.1.0.0/30" subnets_per_network: 2 runner: @@ -316,11 +314,8 @@ NeutronNetworks.create_and_list_routers: - args: - network_create_args: - subnet_create_args: subnet_cidr_start: "1.1.0.0/30" subnets_per_network: 2 - router_create_args: runner: type: "constant" times: {{smoke or 8}} @@ -362,8 +357,6 @@ NeutronNetworks.create_and_list_ports: - args: - network_create_args: - port_create_args: ports_per_network: 4 runner: type: "constant" @@ -403,8 +396,6 @@ NeutronNetworks.create_and_show_ports: - args: - network_create_args: {} - port_create_args: {} ports_per_network: 2 runner: type: "constant" @@ -429,7 +420,6 @@ network_create_args: {} network_update_args: admin_state_up: False - name: "_updated" runner: type: "constant" times: {{smoke or 8}} @@ -454,7 +444,6 @@ subnets_per_network: 2 subnet_update_args: enable_dhcp: False - name: "_subnet_updated" runner: type: "constant" times: {{smoke or 8}} @@ -482,7 +471,6 @@ router_create_args: {} router_update_args: admin_state_up: False - name: "_router_updated" runner: type: "constant" times: {{smoke or 4}} @@ -624,7 +612,6 @@ admin_state_up: False device_id: "dummy_id" device_owner: "dummy_owner" - name: "_port_updated" runner: type: "constant" times: {{smoke or 10}} diff --git a/rally-jobs/rally-mos.yaml b/rally-jobs/rally-mos.yaml deleted file mode 100644 index 093246d2..00000000 --- a/rally-jobs/rally-mos.yaml +++ /dev/null @@ -1,859 +0,0 @@ ---- -{%- set cirros_image_url = "http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-disk.img" %} -{%- set keystone_version = keystone_version|default("v2.0") %} -{% if keystone_version == "v2.0" %} - - SaharaNodeGroupTemplates.create_and_list_node_group_templates: - - - args: - hadoop_version: "{{sahara_hadoop_version}}" - flavor: - name: "m1.small" - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - api_versions: - sahara: - service_type: {{sahara_service_type}} - sla: - failure_rate: - max: 0 - - SaharaNodeGroupTemplates.create_delete_node_group_templates: - - - args: - hadoop_version: "{{sahara_hadoop_version}}" - flavor: - name: "m1.small" - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - api_versions: - sahara: - service_type: {{sahara_service_type}} - sla: - failure_rate: - max: 0 - - KeystoneBasic.create_and_list_tenants: - - - args: {} - runner: - type: "constant" - times: 1 - concurrency: 1 - sla: - failure_rate: - max: 0 - - KeystoneBasic.create_tenant: - - - args: {} - runner: - type: "constant" - times: 1 - concurrency: 1 - sla: - failure_rate: - max: 0 - - KeystoneBasic.create_tenant_with_users: - - - args: - users_per_tenant: 10 - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - sla: - failure_rate: - max: 0 - -{% endif %} - - KeystoneBasic.create_user: - - - args: {} - runner: - type: "constant" - times: 1 - concurrency: 1 - sla: - failure_rate: - max: 0 - - KeystoneBasic.create_delete_user: - - - args: {} - runner: - type: "constant" - times: 1 - concurrency: 1 - sla: - failure_rate: - max: 0 - - KeystoneBasic.create_and_list_users: - - - args: {} - runner: - type: "constant" - times: 1 - concurrency: 1 - sla: - failure_rate: - max: 0 - - HeatStacks.create_and_list_stack: - - - args: - template_path: "~/.rally/extra/default.yaml.template" - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - HeatStacks.create_and_delete_stack: - - - args: - template_path: "~/.rally/extra/default.yaml.template" - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - Authenticate.keystone: - - - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - Authenticate.validate_cinder: - - - args: - repetitions: 2 - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - Authenticate.validate_glance: - - - args: - repetitions: 2 - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - Authenticate.validate_heat: - - - args: - repetitions: 2 - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - Authenticate.validate_nova: - - - args: - repetitions: 2 - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - Quotas.cinder_update_and_delete: - - - args: - max_quota: 1024 - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - Quotas.cinder_update: - - - args: - max_quota: 1024 - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - Quotas.nova_update_and_delete: - - - args: - max_quota: 1024 - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - Quotas.nova_update: - - - args: - max_quota: 1024 - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - VMTasks.boot_runcommand_delete: - - - args: - flavor: - name: "m1.tiny" - image: - name: "TestVM|cirros.*uec" - floating_network: "{{external_net}}" - use_floating_ip: true - command: - script_file: "~/.rally/extra/instance_test.sh" - interpreter: "/bin/sh" - username: "cirros" - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - network: {} - sla: - failure_rate: - max: 0 - - - NovaServers.boot_and_delete_server: - - - args: - flavor: - name: "m1.tiny" - image: - name: "TestVM|cirros.*uec" - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - - - args: - auto_assign_nic: true - flavor: - name: "m1.tiny" - image: - name: "TestVM|cirros.*uec" - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - network: - start_cidr: "10.2.0.0/24" - networks_per_tenant: 2 - sla: - failure_rate: - max: 0 - - - NovaServers.boot_and_list_server: - - - args: - flavor: - name: "m1.tiny" - image: - name: "TestVM|cirros.*uec" - detailed: True - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - NovaServers.list_servers: - - - args: - detailed: True - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - servers: - flavor: - name: "m1.tiny" - image: - name: "TestVM|cirros.*uec" - servers_per_tenant: 1 - sla: - failure_rate: - max: 0 - - NovaServers.boot_and_bounce_server: - - - args: - flavor: - name: "m1.tiny" - image: - name: "TestVM|cirros.*uec" - actions: - - - hard_reboot: 1 - - - stop_start: 1 - - - rescue_unrescue: 1 - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - NovaServers.boot_server: - - - args: - flavor: - name: "^ram64$" - image: - name: "TestVM|cirros.*uec" - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - flavors: - - - name: "ram64" - ram: 64 - sla: - failure_rate: - max: 0 - - - args: - flavor: - name: "m1.tiny" - image: - name: "TestVM|cirros.*uec" - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - NeutronNetworks.create_and_list_networks: - - - args: - network_create_args: - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - quotas: - neutron: - network: -1 - sla: - failure_rate: - max: 0 - - NeutronNetworks.create_and_list_subnets: - - - args: - network_create_args: - subnet_create_args: - subnet_cidr_start: "1.1.0.0/30" - subnets_per_network: 2 - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - network: {} - users: - tenants: 1 - users_per_tenant: 1 - quotas: - neutron: - network: -1 - subnet: -1 - sla: - failure_rate: - max: 0 - - NeutronNetworks.create_and_list_routers: - - - args: - network_create_args: - subnet_create_args: - subnet_cidr_start: "1.1.0.0/30" - subnets_per_network: 2 - router_create_args: - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - network: {} - users: - tenants: 1 - users_per_tenant: 1 - quotas: - neutron: - network: -1 - subnet: -1 - router: -1 - sla: - failure_rate: - max: 0 - - NeutronNetworks.create_and_list_ports: - - - args: - network_create_args: - port_create_args: - ports_per_network: 4 - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - network: {} - users: - tenants: 1 - users_per_tenant: 1 - quotas: - neutron: - network: -1 - subnet: -1 - router: -1 - port: -1 - sla: - failure_rate: - max: 0 - - NeutronNetworks.create_and_update_networks: - - - args: - network_create_args: {} - network_update_args: - admin_state_up: False - name: "_updated" - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - quotas: - neutron: - network: -1 - sla: - failure_rate: - max: 0 - - NeutronNetworks.create_and_update_subnets: - - - args: - network_create_args: {} - subnet_create_args: {} - subnet_cidr_start: "1.4.0.0/16" - subnets_per_network: 2 - subnet_update_args: - enable_dhcp: False - name: "_subnet_updated" - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - network: {} - users: - tenants: 5 - users_per_tenant: 5 - quotas: - neutron: - network: -1 - subnet: -1 - sla: - failure_rate: - max: 0 - - NeutronNetworks.create_and_update_routers: - - - args: - network_create_args: {} - subnet_create_args: {} - subnet_cidr_start: "1.1.0.0/30" - subnets_per_network: 2 - router_create_args: {} - router_update_args: - admin_state_up: False - name: "_router_updated" - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - network: {} - users: - tenants: 1 - users_per_tenant: 1 - quotas: - neutron: - network: -1 - subnet: -1 - router: -1 - sla: - failure_rate: - max: 0 - - NeutronNetworks.create_and_update_ports: - - - args: - network_create_args: {} - port_create_args: {} - ports_per_network: 5 - port_update_args: - admin_state_up: False - device_id: "dummy_id" - device_owner: "dummy_owner" - name: "_port_updated" - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - network: {} - users: - tenants: 1 - users_per_tenant: 1 - quotas: - neutron: - network: -1 - port: -1 - sla: - failure_rate: - max: 0 - - NeutronNetworks.create_and_delete_networks: - - - args: - network_create_args: {} - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - quotas: - neutron: - network: -1 - subnet: -1 - sla: - failure_rate: - max: 0 - - NeutronNetworks.create_and_delete_subnets: - - - args: - network_create_args: {} - subnet_create_args: {} - subnet_cidr_start: "1.1.0.0/30" - subnets_per_network: 2 - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - network: {} - users: - tenants: 1 - users_per_tenant: 1 - quotas: - neutron: - network: -1 - subnet: -1 - sla: - failure_rate: - max: 0 - - NeutronNetworks.create_and_delete_ports: - - - args: - network_create_args: {} - port_create_args: {} - ports_per_network: 10 - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - network: {} - users: - tenants: 1 - users_per_tenant: 1 - quotas: - neutron: - network: -1 - port: -1 - sla: - failure_rate: - max: 0 - - CinderVolumes.create_and_upload_volume_to_image: - - - args: - size: 1 - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - CinderVolumes.create_volume_backup: - - - args: - size: 1 - do_delete: True - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - CinderVolumes.create_and_restore_volume_backup: - - - args: - size: 1 - do_delete: True - runner: - type: "constant" - times: 1 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - CinderVolumes.create_and_list_volume_backups: - - - args: - size: 1 - detailed: True - do_delete: True - runner: - type: "constant" - times: 2 - concurrency: 1 - context: - users: - tenants: 1 - users_per_tenant: 1 - sla: - failure_rate: - max: 0 - - VMTasks.runcommand_heat: - - - args: - workload: - resource: ["rally.plugins.workload", "siege.py"] - username: "fedora" - template: /home/rally/.rally/extra/workload/wordpress_heat_template.yaml - files: - wp-instances.yaml: /home/rally/.rally/extra/workload/wp-instances.yaml - parameters: - wp_instances_count: 2 - wp_instance_type: gig - instance_type: gig - wp_image: fedora - image: fedora - network_id: {{external_net_id}} - context: - users: - tenants: 1 - users_per_tenant: 1 - flavors: - - name: gig - ram: 1024 - disk: 4 - vcpus: 1 - runner: - concurrency: 1 - timeout: 3000 - times: 1 - type: constant - sla: - failure_rate: - max: 100 - - GlanceImages.create_and_update_image: - - - args: - image_location: "{{ cirros_image_url }}" - container_format: "bare" - disk_format: "qcow2" - runner: - type: "constant" - times: 4 - concurrency: 2 - context: - users: - tenants: 2 - users_per_tenant: 2 - api_versions: - glance: - version: 1 - sla: - failure_rate: - max: 100 diff --git a/rally_openstack/common/osclients.py b/rally_openstack/common/osclients.py index ae3270dc..e218c650 100644 --- a/rally_openstack/common/osclients.py +++ b/rally_openstack/common/osclients.py @@ -89,7 +89,7 @@ def configure(name, default_version=None, default_service_type=None, variable is not specified, validation will assume that your client doesn't allow to specify service type. :param supported_versions: List of supported versions(If this variable is - not specified, `OSClients.validate_version` method will raise an + not specified, `OSClient.validate_version` method will raise an exception that client doesn't support setting any versions. If this logic is wrong for your client, you should override `validate_version` in client object) diff --git a/rally_openstack/common/services/network/neutron.py b/rally_openstack/common/services/network/neutron.py index e06005a3..aa63c391 100644 --- a/rally_openstack/common/services/network/neutron.py +++ b/rally_openstack/common/services/network/neutron.py @@ -20,6 +20,7 @@ from rally import exceptions from rally.task import atomic from rally.task import service +from rally_openstack.common import consts from rally_openstack.common.services.network import net_utils @@ -271,17 +272,27 @@ class NeutronService(service.Service): resp = self.client.show_network(network_id, **body) return resp["network"] - def find_network(self, network_id_or_name): + def find_network(self, network_id_or_name, external=_NONE): """Find network by identifier (id or name) :param network_id_or_name: Network ID or name + :param external: check target network is external or not """ + network = None for net in self.list_networks(): if network_id_or_name in (net["name"], net["id"]): - return net - raise exceptions.GetResourceFailure( - resource="network", - err=f"no name or id matches {network_id_or_name}") + network = net + break + if network is None: + raise exceptions.GetResourceFailure( + resource="network", + err=f"no name or id matches {network_id_or_name}") + if external: + if not network.get("router:external", False): + raise exceptions.NotFoundException( + f"Network '{network['name']} (id={network['id']})' is not " + f"external.") + return network @atomic.action_timer("neutron.update_network") @_create_network_arg_adapter() @@ -579,7 +590,7 @@ class NeutronService(service.Service): description=_NONE, discover_external_gw=False, external_gateway_info=_NONE, distributed=_NONE, ha=_NONE, availability_zone_hints=_NONE, service_type_id=_NONE, - flavor_id=_NONE): + flavor_id=_NONE, enable_snat=_NONE): """Create router. :param project_id: The ID of the project that owns the resource. Only @@ -605,12 +616,21 @@ class NeutronService(service.Service): :param service_type_id: The ID of the service type associated with the router. :param flavor_id: The ID of the flavor associated with the router. + :param enable_snat: Whether to include `enable_snat: True` to + external_gateway_info or not. By default, it is enabled if a user + is admin and "ext-gw-mode" extension presents """ if external_gateway_info is _NONE and discover_external_gw: for external_network in self.list_networks(router_external=True): external_gateway_info = {"network_id": external_network["id"]} - if self.supports_extension("ext-gw-mode", silent=True): + if enable_snat is _NONE: + permission = self._clients.credential.permission + is_admin = permission == consts.EndpointPermission.ADMIN + if (self.supports_extension("ext-gw-mode", silent=True) + and is_admin): + external_gateway_info["enable_snat"] = True + elif enable_snat: external_gateway_info["enable_snat"] = True break @@ -856,7 +876,8 @@ class NeutronService(service.Service): self.client.delete_port(port["id"]) except neutron_exceptions.PortNotFoundClient: # port is auto-removed - pass + return False + return True @atomic.action_timer("neutron.list_ports") def list_ports(self, network_id=_NONE, device_id=_NONE, device_owner=_NONE, @@ -918,12 +939,7 @@ class NeutronService(service.Service): if isinstance(floating_network, dict): net_id = floating_network["id"] elif floating_network: - network = self.find_network(floating_network) - if not network.get("router:external", False): - raise exceptions.NotFoundException( - f"Network '{network['name']} (id={network['id']})' is not " - f"external.") - net_id = network["id"] + net_id = self.find_network(floating_network, external=True)["id"] else: ext_networks = self.list_networks(router_external=True) if not ext_networks: diff --git a/rally_openstack/common/wrappers/network.py b/rally_openstack/common/wrappers/network.py index 682385a3..2beb3493 100644 --- a/rally_openstack/common/wrappers/network.py +++ b/rally_openstack/common/wrappers/network.py @@ -61,7 +61,7 @@ class NetworkWrapper(object, metaclass=abc.ABCMeta): START_IPV6_CIDR = "dead:beaf::/64" SERVICE_IMPL = None - def __init__(self, clients, owner, config=None, atomics=None): + def __init__(self, clients, owner, config=None): """Returns available network wrapper instance. :param clients: rally.plugins.openstack.osclients.Clients instance @@ -74,6 +74,7 @@ class NetworkWrapper(object, metaclass=abc.ABCMeta): recognized, 'start_cidr' and 'start_ipv6_cidr'. :returns: NetworkWrapper subclass instance """ + self.clients = clients if hasattr(clients, self.SERVICE_IMPL): self.client = getattr(clients, self.SERVICE_IMPL)() else: @@ -123,6 +124,10 @@ class NeutronWrapper(NetworkWrapper): def neutron(_self): return self.client + @property + def credential(_self): + return self.clients.credential + self.neutron = neutron.NeutronService( clients=_SingleClientWrapper(), name_generator=self.owner.generate_random_name, diff --git a/rally_openstack/task/contexts/keystone/users.py b/rally_openstack/task/contexts/keystone/users.py index 11dc956c..a382ebd9 100644 --- a/rally_openstack/task/contexts/keystone/users.py +++ b/rally_openstack/task/contexts/keystone/users.py @@ -27,7 +27,7 @@ from rally_openstack.common import consts from rally_openstack.common import credential from rally_openstack.common import osclients from rally_openstack.common.services.identity import identity -from rally_openstack.common.wrappers import network +from rally_openstack.common.services.network import neutron from rally_openstack.task import context @@ -35,8 +35,8 @@ LOG = logging.getLogger(__name__) CONF = cfg.CONF -RESOURCE_MANAGEMENT_WORKERS_DESCR = ("The number of concurrent threads to use " - "for serving users context.") +RESOURCE_MANAGEMENT_WORKERS_DESCR = ( + "The number of concurrent threads to use for serving users context.") PROJECT_DOMAIN_DESCR = "ID of domain in which projects will be created." USER_DOMAIN_DESCR = "ID of domain in which users will be created." @@ -135,30 +135,6 @@ class UserGenerator(context.OpenStackContext): for key, value in self.DEFAULT_FOR_NEW_USERS.items(): self.config.setdefault(key, value) - def _remove_default_security_group(self): - """Delete default security group for tenants.""" - clients = osclients.Clients(self.credential) - - if consts.Service.NEUTRON not in clients.services().values(): - return - - use_sg, msg = network.wrap(clients, self).supports_extension( - "security-group") - if not use_sg: - LOG.debug("Security group context is disabled: %s" % msg) - return - - for user, tenant_id in self._iterate_per_tenants(): - with logging.ExceptionLogger( - LOG, "Unable to delete default security group"): - uclients = osclients.Clients(user["credential"]) - security_groups = uclients.neutron()\ - .list_security_groups(tenant_id=tenant_id) - default = [sg for sg in security_groups["security_groups"] - if sg["name"] == "default"] - if default: - clients.neutron().delete_security_group(default[0]["id"]) - def _create_tenants(self, threads): tenants = collections.deque() @@ -237,36 +213,6 @@ class UserGenerator(context.OpenStackContext): broker.run(publish, consume, threads) return list(users) - def _get_consumer_for_deletion(self, func_name): - def consume(cache, resource_id): - if "client" not in cache: - clients = osclients.Clients(self.credential) - cache["client"] = identity.Identity(clients) - getattr(cache["client"], func_name)(resource_id) - return consume - - def _delete_tenants(self): - threads = self.config["resource_management_workers"] - - def publish(queue): - for tenant_id in self.context["tenants"]: - queue.append(tenant_id) - - broker.run(publish, self._get_consumer_for_deletion("delete_project"), - threads) - self.context["tenants"] = {} - - def _delete_users(self): - threads = self.config["resource_management_workers"] - - def publish(queue): - for user in self.context["users"]: - queue.append(user["id"]) - - broker.run(publish, self._get_consumer_for_deletion("delete_user"), - threads) - self.context["users"] = [] - def create_users(self): """Create tenants and users, using the broker pattern.""" @@ -331,6 +277,54 @@ class UserGenerator(context.OpenStackContext): else: self.create_users() + def _remove_default_security_group(self): + """Delete default security group for tenants.""" + + admin_client = neutron.NeutronService( + clients=osclients.Clients(self.credential), + atomic_inst=self.atomic_actions() + ) + + if not admin_client.supports_extension("security-group", silent=True): + LOG.debug("Security group context is disabled.") + return + + security_groups = admin_client.list_security_groups(name="default") + for security_group in security_groups: + if security_group["tenant_id"] not in self.context["tenants"]: + continue + admin_client.delete_security_group(security_group["id"]) + + def _get_consumer_for_deletion(self, func_name): + def consume(cache, resource_id): + if "client" not in cache: + clients = osclients.Clients(self.credential) + cache["client"] = identity.Identity(clients) + getattr(cache["client"], func_name)(resource_id) + return consume + + def _delete_tenants(self): + threads = self.config["resource_management_workers"] + + def publish(queue): + for tenant_id in self.context["tenants"]: + queue.append(tenant_id) + + broker.run(publish, self._get_consumer_for_deletion("delete_project"), + threads) + self.context["tenants"] = {} + + def _delete_users(self): + threads = self.config["resource_management_workers"] + + def publish(queue): + for user in self.context["users"]: + queue.append(user["id"]) + + broker.run(publish, self._get_consumer_for_deletion("delete_user"), + threads) + self.context["users"] = [] + def cleanup(self): """Delete tenants and users, using the broker pattern.""" if self.existing_users: diff --git a/rally_openstack/task/contexts/network/allow_ssh.py b/rally_openstack/task/contexts/network/allow_ssh.py index c52aba93..68524ea2 100644 --- a/rally_openstack/task/contexts/network/allow_ssh.py +++ b/rally_openstack/task/contexts/network/allow_ssh.py @@ -16,8 +16,8 @@ from rally.common import logging from rally.common import validation -from rally_openstack.common import osclients -from rally_openstack.common.wrappers import network +from rally_openstack.common.services.network import neutron +from rally_openstack.task.cleanup import manager as resource_manager from rally_openstack.task import context @@ -50,68 +50,33 @@ def _rule_to_key(rule): "port_range_max", "port_range_min", "protocol", - "remote_ip_prefix", - "security_group_id" + "remote_ip_prefix" ] return "_".join([_normalize_rule_value(x, rule.get(x)) for x in comparison_keys]) -def _prepare_open_secgroup(credential, secgroup_name): - """Generate secgroup allowing all tcp/udp/icmp access. - - In order to run tests on instances it is necessary to have SSH access. - This function generates a secgroup which allows all tcp/udp/icmp access. - - :param credential: clients credential - :param secgroup_name: security group name - - :returns: dict with security group details - """ - neutron = osclients.Clients(credential).neutron() - security_groups = neutron.list_security_groups()["security_groups"] - rally_open = [sg for sg in security_groups if sg["name"] == secgroup_name] - if not rally_open: - descr = "Allow ssh access to VMs created by Rally" - rally_open = neutron.create_security_group( - {"security_group": {"name": secgroup_name, - "description": descr}})["security_group"] - else: - rally_open = rally_open[0] - - rules_to_add = [ - { - "protocol": "tcp", - "port_range_max": 65535, - "port_range_min": 1, - "remote_ip_prefix": "0.0.0.0/0", - "direction": "ingress", - "security_group_id": rally_open["id"] - }, - { - "protocol": "udp", - "port_range_max": 65535, - "port_range_min": 1, - "remote_ip_prefix": "0.0.0.0/0", - "direction": "ingress", - "security_group_id": rally_open["id"] - }, - { - "protocol": "icmp", - "remote_ip_prefix": "0.0.0.0/0", - "direction": "ingress", - "security_group_id": rally_open["id"] - } - ] - - existing_rules = set( - _rule_to_key(r) for r in rally_open.get("security_group_rules", [])) - for new_rule in rules_to_add: - if _rule_to_key(new_rule) not in existing_rules: - neutron.create_security_group_rule( - {"security_group_rule": new_rule}) - - return rally_open +_RULES_TO_ADD = [ + { + "protocol": "tcp", + "port_range_max": 65535, + "port_range_min": 1, + "remote_ip_prefix": "0.0.0.0/0", + "direction": "ingress" + }, + { + "protocol": "udp", + "port_range_max": 65535, + "port_range_min": 1, + "remote_ip_prefix": "0.0.0.0/0", + "direction": "ingress" + }, + { + "protocol": "icmp", + "remote_ip_prefix": "0.0.0.0/0", + "direction": "ingress" + } +] @validation.add("required_platform", platform="openstack", users=True) @@ -120,27 +85,48 @@ class AllowSSH(context.OpenStackContext): """Sets up security groups for all users to access VM via SSH.""" def setup(self): - admin_or_user = (self.context.get("admin") - or self.context.get("users")[0]) + client = neutron.NeutronService( + clients=self.context["users"][0]["credential"].clients(), + name_generator=self.generate_random_name, + atomic_inst=self.atomic_actions() + ) - net_wrapper = network.wrap( - osclients.Clients(admin_or_user["credential"]), - self, config=self.config) - use_sg, msg = net_wrapper.supports_extension("security-group") - if not use_sg: - LOG.info("Security group context is disabled: %s" % msg) + if not client.supports_extension("security-group", silent=True): + LOG.info("Security group context is disabled.") return secgroup_name = self.generate_random_name() + secgroups_per_tenant = {} + for user, tenant_id in self._iterate_per_tenants(): + client = neutron.NeutronService( + clients=user["credential"].clients(), + name_generator=self.generate_random_name, + atomic_inst=self.atomic_actions() + ) + secgroup = client.create_security_group( + name=secgroup_name, + description="Allow ssh access to VMs created by Rally") + secgroups_per_tenant[tenant_id] = secgroup + + existing_rules = set( + _rule_to_key(rule) + for rule in secgroup.get("security_group_rules", [])) + for new_rule in _RULES_TO_ADD: + if _rule_to_key(new_rule) not in existing_rules: + secgroup.setdefault("security_group_rules", []) + secgroup["security_group_rules"].append( + client.create_security_group_rule( + security_group_id=secgroup["id"], **new_rule) + ) + for user in self.context["users"]: - user["secgroup"] = _prepare_open_secgroup(user["credential"], - secgroup_name) + user["secgroup"] = secgroups_per_tenant[user["tenant_id"]] def cleanup(self): - for user, tenant_id in self._iterate_per_tenants(): - with logging.ExceptionLogger( - LOG, - "Unable to delete security group: %s." - % user["secgroup"]["name"]): - clients = osclients.Clients(user["credential"]) - clients.neutron().delete_security_group(user["secgroup"]["id"]) + resource_manager.cleanup( + names=["neutron.security_group"], + admin=self.context.get("admin"), + users=self.context["users"], + task_id=self.get_owner_id(), + superclass=self.__class__ + ) diff --git a/rally_openstack/task/contexts/network/networks.py b/rally_openstack/task/contexts/network/networks.py index f18948e7..baddbea5 100644 --- a/rally_openstack/task/contexts/network/networks.py +++ b/rally_openstack/task/contexts/network/networks.py @@ -17,17 +17,15 @@ from rally.common import logging from rally.common import validation from rally_openstack.common import consts -from rally_openstack.common import osclients -from rally_openstack.common.wrappers import network as network_wrapper +from rally_openstack.common.services.network import neutron +from rally_openstack.task.cleanup import manager as resource_manager from rally_openstack.task import context LOG = logging.getLogger(__name__) -# NOTE(andreykurilin): admin is used only by cleanup -@validation.add("required_platform", platform="openstack", admin=True, - users=True) +@validation.add("required_platform", platform="openstack", users=True) @context.configure(name="network", platform="openstack", order=350) class Network(context.OpenStackContext): """Create networking resources. @@ -67,7 +65,13 @@ class Network(context.OpenStackContext): "type": "object", "properties": { "external": { - "type": "boolean" + "type": "boolean", + "description": "Create a new external router." + }, + "enable_snat": { + "type": "boolean", + "description": "Whether to enable SNAT for a router " + "if there is following extension or not" }, "external_gateway_info": { "description": "The external gateway information .", @@ -90,7 +94,6 @@ class Network(context.OpenStackContext): "networks_per_tenant": 1, "subnets_per_network": 1, "network_create_args": {}, - "dns_nameservers": None, "router": {"external": True}, "dualstack": False } @@ -100,27 +103,47 @@ class Network(context.OpenStackContext): # multithreading/multiprocessing, it is likely the # sockets are left open. This problem is eliminated by # creating a connection in setup and cleanup separately. - net_wrapper = network_wrapper.wrap( - osclients.Clients(self.context["admin"]["credential"]), - self, - config=self.config - ) - kwargs = {} - if self.config["dns_nameservers"] is not None: - kwargs["dns_nameservers"] = self.config["dns_nameservers"] + for user, tenant_id in self._iterate_per_tenants(): self.context["tenants"][tenant_id]["networks"] = [] self.context["tenants"][tenant_id]["subnets"] = [] + client = neutron.NeutronService( + user["credential"].clients(), + name_generator=self.generate_random_name, + atomic_inst=self.atomic_actions() + ) + network_create_args = self.config["network_create_args"].copy() + subnet_create_args = { + "start_cidr": (self.config["start_cidr"] + if not self.config["dualstack"] else None)} + if "dns_nameservers" in self.config: + dns_nameservers = self.config["dns_nameservers"] + subnet_create_args["dns_nameservers"] = dns_nameservers + + router_create_args = dict(self.config["router"] or {}) + if not router_create_args: + # old behaviour - empty dict means no router create + router_create_args = None + elif "external" in router_create_args: + external = router_create_args.pop("external") + router_create_args["discover_external_gw"] = external + for i in range(self.config["networks_per_tenant"]): - network_create_args = self.config["network_create_args"].copy() - net_infra = net_wrapper._create_network_infrastructure( - tenant_id, - dualstack=self.config["dualstack"], - subnets_num=self.config["subnets_per_network"], + + net_infra = client.create_network_topology( network_create_args=network_create_args, - router_create_args=self.config["router"], - **kwargs) + subnet_create_args=subnet_create_args, + subnets_dualstack=self.config["dualstack"], + subnets_count=self.config["subnets_per_network"], + router_create_args=router_create_args) + + if net_infra["routers"]: + router_id = net_infra["routers"][0]["id"] + else: + router_id = None + net_infra["network"]["router_id"] = router_id + self.context["tenants"][tenant_id]["networks"].append( net_infra["network"] ) @@ -129,12 +152,13 @@ class Network(context.OpenStackContext): ) def cleanup(self): - net_wrapper = network_wrapper.wrap( - osclients.Clients(self.context["admin"]["credential"]), - self, config=self.config) - for tenant_id, tenant_ctx in self.context["tenants"].items(): - for network in tenant_ctx.get("networks", []): - with logging.ExceptionLogger( - LOG, - "Failed to delete network for tenant %s" % tenant_id): - net_wrapper.delete_network(network) + resource_manager.cleanup( + names=[ + "neutron.subnet", "neutron.network", "neutron.router", + "neutron.port" + ], + admin=self.context.get("admin"), + users=self.context.get("users", []), + task_id=self.get_owner_id(), + superclass=self.__class__ + ) diff --git a/rally_openstack/task/scenarios/neutron/network.py b/rally_openstack/task/scenarios/neutron/network.py index 30ad8406..0484079d 100644 --- a/rally_openstack/task/scenarios/neutron/network.py +++ b/rally_openstack/task/scenarios/neutron/network.py @@ -28,13 +28,16 @@ LOG = logging.getLogger(__name__) """Scenarios for Neutron.""" +@validation.add("restricted_parameters", + param_names="name", + subdict="network_create_args") @validation.add("required_services", services=[consts.Service.NEUTRON]) @validation.add("required_platform", platform="openstack", users=True) @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.create_and_list_networks", platform="openstack") -class CreateAndListNetworks(utils.NeutronScenario): +class CreateAndListNetworks(utils.NeutronBaseScenario): def run(self, network_create_args=None): """Create a network and then list all networks. @@ -49,17 +52,20 @@ class CreateAndListNetworks(utils.NeutronScenario): :param network_create_args: dict, POST /v2.0/networks request options """ - self._create_network(network_create_args or {}) - self._list_networks() + self.neutron.create_network(**(network_create_args or {})) + self.neutron.list_networks() +@validation.add("restricted_parameters", + param_names="name", + subdict="network_create_args") @validation.add("required_services", services=[consts.Service.NEUTRON]) @validation.add("required_platform", platform="openstack", users=True) @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.create_and_show_network", platform="openstack") -class CreateAndShowNetwork(utils.NeutronScenario): +class CreateAndShowNetwork(utils.NeutronBaseScenario): def run(self, network_create_args=None): """Create a network and show network details. @@ -68,17 +74,23 @@ class CreateAndShowNetwork(utils.NeutronScenario): :param network_create_args: dict, POST /v2.0/networks request options """ - network = self._create_network(network_create_args or {}) - self._show_network(network) + network = self.neutron.create_network(**(network_create_args or {})) + self.neutron.get_network(network["id"]) +@validation.add("restricted_parameters", + param_names="name", + subdict="network_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="network_update_args") @validation.add("required_services", services=[consts.Service.NEUTRON]) @validation.add("required_platform", platform="openstack", users=True) @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.create_and_update_networks", platform="openstack") -class CreateAndUpdateNetworks(utils.NeutronScenario): +class CreateAndUpdateNetworks(utils.NeutronBaseScenario): def run(self, network_update_args, network_create_args=None): """Create and update a network. @@ -88,16 +100,19 @@ class CreateAndUpdateNetworks(utils.NeutronScenario): :param network_update_args: dict, PUT /v2.0/networks update request :param network_create_args: dict, POST /v2.0/networks request options """ - network = self._create_network(network_create_args or {}) - self._update_network(network, network_update_args) + network = self.neutron.create_network(**(network_create_args or {})) + self.neutron.update_network(network["id"], **network_update_args) +@validation.add("restricted_parameters", + param_names="name", + subdict="network_create_args") @validation.add("required_services", services=[consts.Service.NEUTRON]) @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.create_and_delete_networks", platform="openstack") -class CreateAndDeleteNetworks(utils.NeutronScenario): +class CreateAndDeleteNetworks(utils.NeutronBaseScenario): def run(self, network_create_args=None): """Create and delete a network. @@ -106,10 +121,16 @@ class CreateAndDeleteNetworks(utils.NeutronScenario): :param network_create_args: dict, POST /v2.0/networks request options """ - network = self._create_network(network_create_args or {}) - self._delete_network(network["network"]) + network = self.neutron.create_network(**(network_create_args or {})) + self.neutron.delete_network(network["id"]) +@validation.add("restricted_parameters", + param_names="name", + subdict="network_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="subnet_create_args") @validation.add("number", param_name="subnets_per_network", minval=1, integer_only=True) @validation.add("required_services", @@ -118,7 +139,7 @@ class CreateAndDeleteNetworks(utils.NeutronScenario): @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.create_and_list_subnets", platform="openstack") -class CreateAndListSubnets(utils.NeutronScenario): +class CreateAndListSubnets(utils.NeutronBaseScenario): def run(self, network_create_args=None, subnet_create_args=None, subnet_cidr_start=None, subnets_per_network=1): @@ -133,12 +154,23 @@ class CreateAndListSubnets(utils.NeutronScenario): :param subnet_cidr_start: str, start value for subnets CIDR :param subnets_per_network: int, number of subnets for one network """ - network = self._create_network(network_create_args or {}) - self._create_subnets(network, subnet_create_args, subnet_cidr_start, - subnets_per_network) - self._list_subnets() + network = self.neutron.create_network(**(network_create_args or {})) + for _ in range(subnets_per_network): + self.neutron.create_subnet(network["id"], + start_cidr=subnet_cidr_start, + **(subnet_create_args or {})) + self.neutron.list_subnets() +@validation.add("restricted_parameters", + param_names="name", + subdict="network_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="subnet_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="subnet_update_args") @validation.add("number", param_name="subnets_per_network", minval=1, integer_only=True) @validation.add("required_services", @@ -147,7 +179,7 @@ class CreateAndListSubnets(utils.NeutronScenario): @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.create_and_update_subnets", platform="openstack") -class CreateAndUpdateSubnets(utils.NeutronScenario): +class CreateAndUpdateSubnets(utils.NeutronBaseScenario): def run(self, subnet_update_args, network_create_args=None, subnet_create_args=None, subnet_cidr_start=None, @@ -165,14 +197,24 @@ class CreateAndUpdateSubnets(utils.NeutronScenario): :param subnet_cidr_start: str, start value for subnets CIDR :param subnets_per_network: int, number of subnets for one network """ - network = self._create_network(network_create_args or {}) - subnets = self._create_subnets(network, subnet_create_args, - subnet_cidr_start, subnets_per_network) - + network = self.neutron.create_network(**(network_create_args or {})) + subnets = [] + for _ in range(subnets_per_network): + subnets.append( + self.neutron.create_subnet( + network["id"], start_cidr=subnet_cidr_start, + **(subnet_create_args or {})) + ) for subnet in subnets: - self._update_subnet(subnet, subnet_update_args) + self.neutron.update_subnet(subnet["id"], **subnet_update_args) +@validation.add("restricted_parameters", + param_names="name", + subdict="network_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="subnet_create_args") @validation.add("number", param_name="subnets_per_network", minval=1, integer_only=True) @validation.add("required_services", @@ -181,7 +223,7 @@ class CreateAndUpdateSubnets(utils.NeutronScenario): @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.create_and_show_subnets", platform="openstack") -class CreateAndShowSubnets(utils.NeutronScenario): +class CreateAndShowSubnets(utils.NeutronBaseScenario): def run(self, network_create_args=None, subnet_create_args=None, subnet_cidr_start=None, @@ -198,14 +240,24 @@ class CreateAndShowSubnets(utils.NeutronScenario): :param subnet_cidr_start: str, start value for subnets CIDR :param subnets_per_network: int, number of subnets for one network """ - network = self._get_or_create_network(network_create_args) - subnets = self._create_subnets(network, subnet_create_args, - subnet_cidr_start, subnets_per_network) - + network = self._get_or_create_network(**(network_create_args or {})) + subnets = [] + for _ in range(subnets_per_network): + subnets.append( + self.neutron.create_subnet( + network["id"], start_cidr=subnet_cidr_start, + **(subnet_create_args or {})) + ) for subnet in subnets: - self._show_subnet(subnet) + self.neutron.get_subnet(subnet["id"]) +@validation.add("restricted_parameters", + param_names="name", + subdict="network_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="subnet_create_args") @validation.add("number", param_name="subnets_per_network", minval=1, integer_only=True) @validation.add("required_services", @@ -213,7 +265,7 @@ class CreateAndShowSubnets(utils.NeutronScenario): @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.create_and_delete_subnets", platform="openstack") -class CreateAndDeleteSubnets(utils.NeutronScenario): +class CreateAndDeleteSubnets(utils.NeutronBaseScenario): def run(self, network_create_args=None, subnet_create_args=None, subnet_cidr_start=None, subnets_per_network=1): @@ -228,14 +280,27 @@ class CreateAndDeleteSubnets(utils.NeutronScenario): :param subnet_cidr_start: str, start value for subnets CIDR :param subnets_per_network: int, number of subnets for one network """ - network = self._get_or_create_network(network_create_args) - subnets = self._create_subnets(network, subnet_create_args, - subnet_cidr_start, subnets_per_network) - + network = self._get_or_create_network(**(network_create_args or {})) + subnets = [] + for _ in range(subnets_per_network): + subnets.append( + self.neutron.create_subnet( + network["id"], start_cidr=subnet_cidr_start, + **(subnet_create_args or {})) + ) for subnet in subnets: - self._delete_subnet(subnet) + self.neutron.delete_subnet(subnet["id"]) +@validation.add("restricted_parameters", + param_names="name", + subdict="network_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="subnet_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="router_create_args") @validation.add("number", param_name="subnets_per_network", minval=1, integer_only=True) @validation.add("required_services", @@ -244,7 +309,7 @@ class CreateAndDeleteSubnets(utils.NeutronScenario): @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.create_and_list_routers", platform="openstack") -class CreateAndListRouters(utils.NeutronScenario): +class CreateAndListRouters(utils.NeutronBaseScenario): def run(self, network_create_args=None, subnet_create_args=None, subnet_cidr_start=None, subnets_per_network=1, @@ -261,12 +326,28 @@ class CreateAndListRouters(utils.NeutronScenario): :param subnets_per_network: int, number of subnets for one network :param router_create_args: dict, POST /v2.0/routers request options """ - self._create_network_structure(network_create_args, subnet_create_args, - subnet_cidr_start, subnets_per_network, - router_create_args) - self._list_routers() + subnet_create_args = dict(subnet_create_args or {}) + subnet_create_args["start_cidr"] = subnet_cidr_start + + self.neutron.create_network_topology( + network_create_args=(network_create_args or {}), + router_create_args=(router_create_args or {}), + router_per_subnet=True, + subnet_create_args=subnet_create_args, + subnets_count=subnets_per_network + ) + self.neutron.list_routers() +@validation.add("restricted_parameters", + param_names="name", + subdict="network_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="subnet_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="router_create_args") @validation.add("number", param_name="subnets_per_network", minval=1, integer_only=True) @validation.add("required_services", services=[consts.Service.NEUTRON]) @@ -274,7 +355,7 @@ class CreateAndListRouters(utils.NeutronScenario): @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.create_and_show_routers", platform="openstack") -class CreateAndShowRouters(utils.NeutronScenario): +class CreateAndShowRouters(utils.NeutronBaseScenario): def run(self, network_create_args=None, subnet_create_args=None, subnet_cidr_start=None, subnets_per_network=1, @@ -291,14 +372,33 @@ class CreateAndShowRouters(utils.NeutronScenario): :param subnets_per_network: int, number of subnets for each network :param router_create_args: dict, POST /v2.0/routers request options """ - network, subnets, routers = self._create_network_structure( - network_create_args, subnet_create_args, subnet_cidr_start, - subnets_per_network, router_create_args) + subnet_create_args = dict(subnet_create_args or {}) + subnet_create_args["start_cidr"] = subnet_cidr_start - for router in routers: - self._show_router(router) + net_topo = self.neutron.create_network_topology( + network_create_args=(network_create_args or {}), + router_create_args=(router_create_args or {}), + router_per_subnet=True, + subnet_create_args=subnet_create_args, + subnets_count=subnets_per_network + ) + + for router in net_topo["routers"]: + self.neutron.get_router(router["id"]) +@validation.add("restricted_parameters", + param_names="name", + subdict="network_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="subnet_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="router_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="router_update_args") @validation.add("number", param_name="subnets_per_network", minval=1, integer_only=True) @validation.add("required_services", @@ -306,7 +406,7 @@ class CreateAndShowRouters(utils.NeutronScenario): @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.create_and_update_routers", platform="openstack") -class CreateAndUpdateRouters(utils.NeutronScenario): +class CreateAndUpdateRouters(utils.NeutronBaseScenario): def run(self, router_update_args, network_create_args=None, subnet_create_args=None, subnet_cidr_start=None, @@ -324,14 +424,30 @@ class CreateAndUpdateRouters(utils.NeutronScenario): :param subnets_per_network: int, number of subnets for one network :param router_create_args: dict, POST /v2.0/routers request options """ - network, subnets, routers = self._create_network_structure( - network_create_args, subnet_create_args, subnet_cidr_start, - subnets_per_network, router_create_args) + subnet_create_args = dict(subnet_create_args or {}) + subnet_create_args["start_cidr"] = subnet_cidr_start - for router in routers: - self._update_router(router, router_update_args) + net_topo = self.neutron.create_network_topology( + network_create_args=(network_create_args or {}), + router_create_args=(router_create_args or {}), + router_per_subnet=True, + subnet_create_args=subnet_create_args, + subnets_count=subnets_per_network + ) + + for router in net_topo["routers"]: + self.neutron.update_router(router["id"], **router_update_args) +@validation.add("restricted_parameters", + param_names="name", + subdict="network_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="subnet_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="router_create_args") @validation.add("number", param_name="subnets_per_network", minval=1, integer_only=True) @validation.add("required_services", @@ -339,7 +455,7 @@ class CreateAndUpdateRouters(utils.NeutronScenario): @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.create_and_delete_routers", platform="openstack") -class CreateAndDeleteRouters(utils.NeutronScenario): +class CreateAndDeleteRouters(utils.NeutronBaseScenario): def run(self, network_create_args=None, subnet_create_args=None, subnet_cidr_start=None, subnets_per_network=1, @@ -356,24 +472,38 @@ class CreateAndDeleteRouters(utils.NeutronScenario): :param subnets_per_network: int, number of subnets for one network :param router_create_args: dict, POST /v2.0/routers request options """ - network, subnets, routers = self._create_network_structure( - network_create_args, subnet_create_args, subnet_cidr_start, - subnets_per_network, router_create_args) + subnet_create_args = dict(subnet_create_args or {}) + subnet_create_args["start_cidr"] = subnet_cidr_start + + net_topo = self.neutron.create_network_topology( + network_create_args=(network_create_args or {}), + router_create_args=(router_create_args or {}), + router_per_subnet=True, + subnet_create_args=subnet_create_args, + subnets_count=subnets_per_network + ) for e in range(subnets_per_network): - router = routers[e] - subnet = subnets[e] - self._remove_interface_router(subnet["subnet"], router["router"]) - self._delete_router(router) + router = net_topo["routers"][e] + subnet = net_topo["subnets"][e] + self.neutron.remove_interface_from_router(subnet_id=subnet["id"], + router_id=router["id"]) + self.neutron.delete_router(router["id"]) +@validation.add("restricted_parameters", + param_names="name", + subdict="network_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="router_create_args") @validation.add("required_services", services=[consts.Service.NEUTRON]) @validation.add("required_platform", platform="openstack", users=True) @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.set_and_clear_router_gateway", platform="openstack") -class SetAndClearRouterGateway(utils.NeutronScenario): +class SetAndClearRouterGateway(utils.NeutronBaseScenario): def run(self, enable_snat=True, network_create_args=None, router_create_args=None): @@ -390,12 +520,21 @@ class SetAndClearRouterGateway(utils.NeutronScenario): """ network_create_args = network_create_args or {} router_create_args = router_create_args or {} - ext_net = self._create_network(network_create_args) - router = self._create_router(router_create_args) - self._add_gateway_router(router, ext_net, enable_snat) - self._remove_gateway_router(router) + + ext_net = self.neutron.create_network(**network_create_args) + router = self.neutron.create_router(**router_create_args) + self.neutron.add_gateway_to_router(router_id=router["id"], + network_id=ext_net["id"], + enable_snat=enable_snat) + self.neutron.remove_gateway_from_router(router["id"]) +@validation.add("restricted_parameters", + param_names="name", + subdict="network_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="port_create_args") @validation.add("number", param_name="ports_per_network", minval=1, integer_only=True) @validation.add("required_services", @@ -404,7 +543,7 @@ class SetAndClearRouterGateway(utils.NeutronScenario): @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.create_and_list_ports", platform="openstack") -class CreateAndListPorts(utils.NeutronScenario): +class CreateAndListPorts(utils.NeutronBaseScenario): def run(self, network_create_args=None, port_create_args=None, ports_per_network=1): @@ -415,13 +554,22 @@ class CreateAndListPorts(utils.NeutronScenario): :param port_create_args: dict, POST /v2.0/ports request options :param ports_per_network: int, number of ports for one network """ - network = self._get_or_create_network(network_create_args) + network = self._get_or_create_network(**(network_create_args or {})) for i in range(ports_per_network): - self._create_port(network, port_create_args or {}) + self.neutron.create_port(network["id"], **(port_create_args or {})) - self._list_ports() + self.neutron.list_ports() +@validation.add("restricted_parameters", + param_names="name", + subdict="network_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="port_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="port_update_args") @validation.add("number", param_name="ports_per_network", minval=1, integer_only=True) @validation.add("required_services", @@ -430,7 +578,7 @@ class CreateAndListPorts(utils.NeutronScenario): @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.create_and_update_ports", platform="openstack") -class CreateAndUpdatePorts(utils.NeutronScenario): +class CreateAndUpdatePorts(utils.NeutronBaseScenario): def run(self, port_update_args, network_create_args=None, port_create_args=None, ports_per_network=1): @@ -445,12 +593,19 @@ class CreateAndUpdatePorts(utils.NeutronScenario): :param port_create_args: dict, POST /v2.0/ports request options :param ports_per_network: int, number of ports for one network """ - network = self._get_or_create_network(network_create_args) + network = self._get_or_create_network(**(network_create_args or {})) for i in range(ports_per_network): - port = self._create_port(network, port_create_args) - self._update_port(port, port_update_args) + port = self.neutron.create_port( + network["id"], **(port_create_args or {})) + self.neutron.update_port(port["id"], **port_update_args) +@validation.add("restricted_parameters", + param_names="name", + subdict="network_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="port_create_args") @validation.add("number", param_name="ports_per_network", minval=1, integer_only=True) @validation.add("required_services", @@ -459,7 +614,7 @@ class CreateAndUpdatePorts(utils.NeutronScenario): @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.create_and_show_ports", platform="openstack") -class CreateAndShowPorts(utils.NeutronScenario): +class CreateAndShowPorts(utils.NeutronBaseScenario): def run(self, network_create_args=None, port_create_args=None, ports_per_network=1): @@ -473,21 +628,20 @@ class CreateAndShowPorts(utils.NeutronScenario): :param port_create_args: dict, POST /v2.0/ports request options :param ports_per_network: int, number of ports for one network """ - network_create_args = network_create_args or {} - port_create_args = port_create_args or {} - - network = self._get_or_create_network(network_create_args) + network = self._get_or_create_network(**(network_create_args or {})) for i in range(ports_per_network): - port = self._create_port(network, port_create_args) - msg = "Port isn't created" - self.assertTrue(port, err_msg=msg) + port = self.neutron.create_port( + network["id"], **(port_create_args or {})) - port_info = self._show_port(port) - msg = "Created port and Showed port isn't equal" - self.assertEqual(port["port"]["id"], port_info["port"]["id"], - err_msg=msg) + self.neutron.get_port(port["id"]) +@validation.add("restricted_parameters", + param_names="name", + subdict="network_create_args") +@validation.add("restricted_parameters", + param_names="name", + subdict="port_create_args") @validation.add("number", param_name="ports_per_network", minval=1, integer_only=True) @validation.add("required_services", @@ -495,7 +649,7 @@ class CreateAndShowPorts(utils.NeutronScenario): @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.create_and_delete_ports", platform="openstack") -class CreateAndDeletePorts(utils.NeutronScenario): +class CreateAndDeletePorts(utils.NeutronBaseScenario): def run(self, network_create_args=None, port_create_args=None, ports_per_network=1): @@ -509,10 +663,12 @@ class CreateAndDeletePorts(utils.NeutronScenario): :param port_create_args: dict, POST /v2.0/ports request options :param ports_per_network: int, number of ports for one network """ - network = self._get_or_create_network(network_create_args) + network = self._get_or_create_network(**(network_create_args or {})) for i in range(ports_per_network): - port = self._create_port(network, port_create_args) - self._delete_port(port) + port = self.neutron.create_port( + network["id"], **(port_create_args or {})) + + self.neutron.delete_port(port["id"]) @validation.add("number", param_name="ports_per_network", minval=1, @@ -527,7 +683,7 @@ class CreateAndDeletePorts(utils.NeutronScenario): "network@openstack": {}}, name="NeutronNetworks.create_and_bind_ports", platform="openstack") -class CreateAndBindPorts(utils.NeutronScenario): +class CreateAndBindPorts(utils.NeutronBaseScenario): def run(self, ports_per_network=1): """Bind a given number of ports. @@ -558,29 +714,17 @@ class CreateAndBindPorts(utils.NeutronScenario): tenant_id = self.context["tenant"]["id"] for network in self.context["tenants"][tenant_id]["networks"]: - wrapped_network = {"network": network} - - self._create_subnet( - wrapped_network, - start_cidr="10.2.0.0/24", - subnet_create_args={}, - ) - self._create_subnet( - wrapped_network, - start_cidr="2001:db8:1:1::/64", - subnet_create_args={}, - ) + self.neutron.create_subnet(network_id=network["id"], ip_version=4) + self.neutron.create_subnet(network_id=network["id"], ip_version=6) for i in range(ports_per_network): - port = self._create_port(wrapped_network, port_create_args={}) + port = self.neutron.create_port(network_id=network["id"]) # port bind needs admin role - self._update_port( - port, - port_update_args={ - "device_owner": "compute:nova", - "device_id": "ba805478-85ff-11e9-a2e4-2b8dea218fc8", - "binding:host_id": host_to_bind, - }, + self.admin_neutron.update_port( + port_id=port["id"], + device_owner="compute:nova", + device_id="ba805478-85ff-11e9-a2e4-2b8dea218fc8", + **{"binding:host_id": host_to_bind}, ) @@ -591,7 +735,7 @@ class CreateAndBindPorts(utils.NeutronScenario): @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.create_and_list_floating_ips", platform="openstack") -class CreateAndListFloatingIps(utils.NeutronScenario): +class CreateAndListFloatingIps(utils.NeutronBaseScenario): def run(self, floating_network=None, floating_ip_args=None): """Create and list floating IPs. @@ -603,8 +747,9 @@ class CreateAndListFloatingIps(utils.NeutronScenario): :param floating_ip_args: dict, POST /floatingips request options """ floating_ip_args = floating_ip_args or {} - self._create_floatingip(floating_network, **floating_ip_args) - self._list_floating_ips() + self.neutron.create_floatingip(floating_network=floating_network, + **floating_ip_args) + self.neutron.list_floatingips() @validation.add("required_services", @@ -614,7 +759,7 @@ class CreateAndListFloatingIps(utils.NeutronScenario): @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.create_and_delete_floating_ips", platform="openstack") -class CreateAndDeleteFloatingIps(utils.NeutronScenario): +class CreateAndDeleteFloatingIps(utils.NeutronBaseScenario): def run(self, floating_network=None, floating_ip_args=None): """Create and delete floating IPs. @@ -626,9 +771,9 @@ class CreateAndDeleteFloatingIps(utils.NeutronScenario): :param floating_ip_args: dict, POST /floatingips request options """ floating_ip_args = floating_ip_args or {} - floating_ip = self._create_floatingip(floating_network, - **floating_ip_args) - self._delete_floating_ip(floating_ip["floatingip"]) + floatingip = self.neutron.create_floatingip( + floating_network=floating_network, **floating_ip_args) + self.neutron.delete_floatingip(floatingip["id"]) @validation.add("required_services", @@ -639,7 +784,7 @@ class CreateAndDeleteFloatingIps(utils.NeutronScenario): context={"cleanup@openstack": ["neutron"]}, name="NeutronNetworks.associate_and_dissociate_floating_ips", platform="openstack") -class AssociateAndDissociateFloatingIps(utils.NeutronScenario): +class AssociateAndDissociateFloatingIps(utils.NeutronBaseScenario): def run(self, floating_network=None): """Associate and dissociate floating IPs. @@ -658,40 +803,31 @@ class AssociateAndDissociateFloatingIps(utils.NeutronScenario): :param floating_network: str, external network for floating IP creation """ - floating_ip = self._create_floatingip( - floating_network) + floating_network = self.neutron.find_network(floating_network, + external=True) + floating_ip = self.neutron.create_floatingip( + floating_network=floating_network) - private_network = self._create_network( - network_create_args={}) - subnet = self._create_subnet( - network=private_network, - subnet_create_args={}) - port = self._create_port( - network=private_network, - port_create_args={}) + private_network = self.neutron.create_network() + subnet = self.neutron.create_subnet(network_id=private_network["id"]) + port = self.neutron.create_port(network_id=private_network["id"]) - router = self._create_router( - router_create_args={}) - floating_network_id = self._get_network_id(floating_network) - self._add_gateway_router( - router, - {"network": {"id": floating_network_id}}) - self._add_interface_router( - subnet["subnet"], - router["router"]) + router = self.neutron.create_router() + self.neutron.add_gateway_to_router( + router["id"], network_id=floating_network["id"]) + self.neutron.add_interface_to_router( + subnet_id=subnet["id"], router_id=router["id"]) - self._associate_floating_ip( - floatingip=floating_ip["floatingip"], - port=port["port"]) - self._dissociate_floating_ip( - floatingip=floating_ip["floatingip"]) + self.neutron.associate_floatingip( + floatingip_id=floating_ip["id"], port_id=port["id"]) + self.neutron.dissociate_floatingip(floatingip_id=floating_ip["id"]) @validation.add("required_services", services=[consts.Service.NEUTRON]) @validation.add("required_platform", platform="openstack", users=True) @scenario.configure(name="NeutronNetworks.list_agents", platform="openstack") -class ListAgents(utils.NeutronScenario): +class ListAgents(utils.NeutronBaseScenario): def run(self, agent_args=None): """List all neutron agents. @@ -702,7 +838,7 @@ class ListAgents(utils.NeutronScenario): :param agent_args: dict, POST /v2.0/agents request options """ agent_args = agent_args or {} - self._list_agents(**agent_args) + self.neutron.list_agents(**agent_args) @validation.add("required_services", @@ -712,7 +848,7 @@ class ListAgents(utils.NeutronScenario): @scenario.configure(context={"cleanup@openstack": ["neutron"]}, name="NeutronSubnets.delete_subnets", platform="openstack") -class DeleteSubnets(utils.NeutronScenario): +class DeleteSubnets(utils.NeutronBaseScenario): def run(self): """Delete a subnet that belongs to each precreated network. @@ -733,4 +869,4 @@ class DeleteSubnets(utils.NeutronScenario): for network in self.context["tenants"][tenant_id]["networks"]: # delete one of subnets based on the user sequential number subnet_id = network["subnets"][number] - self._delete_subnet({"subnet": {"id": subnet_id}}) + self.neutron.delete_subnet(subnet_id) diff --git a/rally_openstack/task/scenarios/neutron/utils.py b/rally_openstack/task/scenarios/neutron/utils.py index 7941355a..7d69dde1 100644 --- a/rally_openstack/task/scenarios/neutron/utils.py +++ b/rally_openstack/task/scenarios/neutron/utils.py @@ -42,6 +42,31 @@ class NeutronBaseScenario(scenario.OpenStackScenario): name_generator=self.generate_random_name, atomic_inst=self.atomic_actions() ) + if hasattr(self, "_admin_clients"): + self.admin_neutron = neutron.NeutronService( + clients=self._admin_clients, + name_generator=self.generate_random_name, + atomic_inst=self.atomic_actions() + ) + + def _get_or_create_network(self, **network_create_args): + """Get a network from context, or create a new one. + + This lets users either create networks with the 'network' + context, provide existing networks with the 'existing_network' + context, or let the scenario create a default network for + them. + """ + + if "networks" in self.context["tenant"]: + networks = self.context["tenant"]["networks"] + net_idx = self.context["iteration"] % len(networks) + return networks[net_idx] + else: + LOG.warning("Running this scenario without either the " + "'network@openstack' or 'existing_network@openstack' " + "context is deprecated since Rally-OpenStack 2.0.0.") + return self.neutron.create_network(**network_create_args) class NeutronScenario(NeutronBaseScenario): diff --git a/rally_openstack/task/scenarios/nova/servers.py b/rally_openstack/task/scenarios/nova/servers.py index bee5acb8..c3938954 100644 --- a/rally_openstack/task/scenarios/nova/servers.py +++ b/rally_openstack/task/scenarios/nova/servers.py @@ -20,7 +20,6 @@ from rally.task import types from rally.task import validation from rally_openstack.common import consts -from rally_openstack.common.wrappers import network as network_wrapper from rally_openstack.task import scenario from rally_openstack.task.scenarios.cinder import utils as cinder_utils from rally_openstack.task.scenarios.neutron import utils as neutron_utils @@ -37,7 +36,7 @@ LOG = logging.getLogger(__name__) flavor={"type": "nova_flavor"}) @validation.add("image_valid_on_flavor", flavor_param="flavor", image_param="image") -@validation.add("required_services", services=(consts.Service.NOVA)) +@validation.add("required_services", services=[consts.Service.NOVA]) @validation.add("required_platform", platform="openstack", users=True) @scenario.configure(context={"cleanup@openstack": ["nova"]}, name="NovaServers.boot_and_list_server", @@ -926,9 +925,8 @@ class BootAndAssociateFloatingIp(utils.NovaScenario): """ create_floating_ip_args = create_floating_ip_args or {} server = self._boot_server(image, flavor, **kwargs) - address = network_wrapper.wrap(self.clients, self).create_floating_ip( - tenant_id=server.tenant_id, **create_floating_ip_args) - self._associate_floating_ip(server, address["ip"]) + floatingip = self.neutron.create_floatingip(**create_floating_ip_args) + self._associate_floating_ip(server, floatingip) @types.convert(image={"type": "glance_image"}, @@ -1114,10 +1112,9 @@ class BootServerAssociateAndDissociateFloatingIP(utils.NovaScenario): create_floating_ip_args = create_floating_ip_args or {} server = self._boot_server(image, flavor, **kwargs) - address = network_wrapper.wrap(self.clients, self).create_floating_ip( - tenant_id=server.tenant_id, **create_floating_ip_args) - self._associate_floating_ip(server, address["ip"]) - self._dissociate_floating_ip(server, address["ip"]) + floatingip = self.neutron.create_floatingip(**create_floating_ip_args) + self._associate_floating_ip(server, floatingip) + self._dissociate_floating_ip(server, floatingip) @types.convert(image={"type": "glance_image"}, diff --git a/rally_openstack/task/scenarios/vm/utils.py b/rally_openstack/task/scenarios/vm/utils.py index ea71eb9f..f9976f04 100644 --- a/rally_openstack/task/scenarios/vm/utils.py +++ b/rally_openstack/task/scenarios/vm/utils.py @@ -26,7 +26,6 @@ from rally.task import atomic from rally.task import utils from rally.utils import sshutils -from rally_openstack.common.wrappers import network as network_wrapper from rally_openstack.task.scenarios.nova import utils as nova_utils LOG = logging.getLogger(__name__) @@ -161,30 +160,23 @@ class VMScenario(nova_utils.NovaScenario): "id": fip.get("id"), "is_floating": use_floating_ip} - @atomic.action_timer("vm.attach_floating_ip") def _attach_floating_ip(self, server, floating_network): internal_network = list(server.networks)[0] fixed_ip = server.addresses[internal_network][0]["addr"] - with atomic.ActionTimer(self, "neutron.create_floating_ip"): - fip = network_wrapper.wrap(self.clients, self).create_floating_ip( - ext_network=floating_network, - tenant_id=server.tenant_id, fixed_ip=fixed_ip) + floatingip = self.neutron.create_floatingip( + floating_network=floating_network) + self._associate_floating_ip(server, floatingip, fixed_address=fixed_ip) - self._associate_floating_ip(server, fip, fixed_address=fixed_ip) + return {"id": floatingip["id"], + "ip": floatingip["floating_ip_address"]} - return fip - - @atomic.action_timer("vm.delete_floating_ip") def _delete_floating_ip(self, server, fip): with logging.ExceptionLogger( LOG, "Unable to delete IP: %s" % fip["ip"]): if self.check_ip_address(fip["ip"])(server): self._dissociate_floating_ip(server, fip) - with atomic.ActionTimer(self, "neutron.delete_floating_ip"): - network_wrapper.wrap(self.clients, - self).delete_floating_ip( - fip["id"], wait=True) + self.neutron.delete_floatingip(fip["id"]) def _delete_server_with_fip(self, server, fip, force_delete=False): if fip["is_floating"]: diff --git a/rally_openstack/verification/tempest/context.py b/rally_openstack/verification/tempest/context.py index efb2ba54..cca6c3d0 100644 --- a/rally_openstack/verification/tempest/context.py +++ b/rally_openstack/verification/tempest/context.py @@ -28,7 +28,7 @@ from rally.verification import utils from rally_openstack.common import consts from rally_openstack.common import credential from rally_openstack.common.services.image import image -from rally_openstack.common.wrappers import network +from rally_openstack.common.services.network import neutron from rally_openstack.verification.tempest import config as conf @@ -287,25 +287,29 @@ class TempestContext(context.VerifierContext): return flavor def _create_network_resources(self): - neutron_wrapper = network.NeutronWrapper(self.clients, self) + client = neutron.NeutronService( + clients=self.clients, + name_generator=self.generate_random_name, + atomic_inst=self.atomic_actions() + ) tenant_id = self.clients.keystone.auth_ref.project_id - router_create_args = {} + router_create_args = {"project_id": tenant_id} public_net = None if self.conf.has_section("network"): public_net = self.conf.get("network", "public_network_id") if public_net: - ext_gw_mode_enabled = neutron_wrapper.ext_gw_mode_enabled external_gateway_info = { "network_id": public_net } - if ext_gw_mode_enabled: + if client.supports_extension("ext-gw-mode", silent=True): external_gateway_info["enable_snat"] = True router_create_args["external_gateway_info"] = external_gateway_info LOG.debug("Creating network resources: network, subnet, router.") - net = neutron_wrapper.create_network( - tenant_id, subnets_num=1, add_router=True, + net = client.create_network_topology( + subnets_count=1, router_create_args=router_create_args, - network_create_args={"shared": True}) + subnet_create_args={"project_id": tenant_id}, + network_create_args={"shared": True, "project_id": tenant_id}) LOG.debug("Network resources have been successfully created!") self._created_networks.append(net) @@ -343,11 +347,16 @@ class TempestContext(context.VerifierContext): self._remove_opt_value_from_config("orchestration", flavor.id) def _cleanup_network_resources(self): - neutron_wrapper = network.NeutronWrapper(self.clients, self) - for net in self._created_networks: + client = neutron.NeutronService( + clients=self.clients, + name_generator=self.generate_random_name, + atomic_inst=self.atomic_actions() + ) + for topo in self._created_networks: LOG.debug("Deleting network resources: router, subnet, network.") - neutron_wrapper.delete_network(net) - self._remove_opt_value_from_config("compute", net["name"]) + client.delete_network_topology(topo) + self._remove_opt_value_from_config("compute", + topo["network"]["name"]) LOG.debug("Network resources have been deleted.") def _remove_opt_value_from_config(self, section, opt_value): diff --git a/samples/tasks/scenarios/neutron/create-and-update-networks.json b/samples/tasks/scenarios/neutron/create-and-update-networks.json index 6b04bc0a..60a7b119 100644 --- a/samples/tasks/scenarios/neutron/create-and-update-networks.json +++ b/samples/tasks/scenarios/neutron/create-and-update-networks.json @@ -3,10 +3,8 @@ { "args": { "network_update_args": { - "admin_state_up": false, - "name": "_updated" - }, - "network_create_args": {} + "admin_state_up": false + } }, "runner": { "type": "constant", diff --git a/samples/tasks/scenarios/neutron/create-and-update-networks.yaml b/samples/tasks/scenarios/neutron/create-and-update-networks.yaml index 43934bcf..b8ed3daa 100644 --- a/samples/tasks/scenarios/neutron/create-and-update-networks.yaml +++ b/samples/tasks/scenarios/neutron/create-and-update-networks.yaml @@ -2,10 +2,8 @@ NeutronNetworks.create_and_update_networks: - args: - network_create_args: {} network_update_args: admin_state_up: False - name: "_updated" runner: type: "constant" times: 10 diff --git a/samples/tasks/scenarios/neutron/create-and-update-ports.json b/samples/tasks/scenarios/neutron/create-and-update-ports.json index 228744ca..2a658b03 100644 --- a/samples/tasks/scenarios/neutron/create-and-update-ports.json +++ b/samples/tasks/scenarios/neutron/create-and-update-ports.json @@ -2,13 +2,10 @@ "NeutronNetworks.create_and_update_ports": [ { "args": { - "network_create_args": {}, - "port_create_args": {}, "port_update_args": { "admin_state_up": false, "device_id": "dummy_id", - "device_owner": "dummy_owner", - "name": "_port_updated" + "device_owner": "dummy_owner" }, "ports_per_network": 5 }, diff --git a/samples/tasks/scenarios/neutron/create-and-update-ports.yaml b/samples/tasks/scenarios/neutron/create-and-update-ports.yaml index f315b117..7dba1730 100644 --- a/samples/tasks/scenarios/neutron/create-and-update-ports.yaml +++ b/samples/tasks/scenarios/neutron/create-and-update-ports.yaml @@ -2,14 +2,11 @@ NeutronNetworks.create_and_update_ports: - args: - network_create_args: {} - port_create_args: {} ports_per_network: 5 port_update_args: admin_state_up: False device_id: "dummy_id" device_owner: "dummy_owner" - name: "_port_updated" runner: type: "constant" times: 10 diff --git a/samples/tasks/scenarios/neutron/create-and-update-routers.json b/samples/tasks/scenarios/neutron/create-and-update-routers.json index fa2d2a0d..1f582224 100644 --- a/samples/tasks/scenarios/neutron/create-and-update-routers.json +++ b/samples/tasks/scenarios/neutron/create-and-update-routers.json @@ -2,14 +2,10 @@ "NeutronNetworks.create_and_update_routers": [ { "args": { - "network_create_args": {}, - "subnet_create_args": {}, "subnet_cidr_start": "1.1.0.0/30", "subnets_per_network": 2, - "router_create_args": {}, "router_update_args": { - "admin_state_up": false, - "name": "_router_updated" + "admin_state_up": false } }, "runner": { diff --git a/samples/tasks/scenarios/neutron/create-and-update-routers.yaml b/samples/tasks/scenarios/neutron/create-and-update-routers.yaml index f68d2477..99a103e4 100644 --- a/samples/tasks/scenarios/neutron/create-and-update-routers.yaml +++ b/samples/tasks/scenarios/neutron/create-and-update-routers.yaml @@ -2,14 +2,10 @@ NeutronNetworks.create_and_update_routers: - args: - network_create_args: {} - subnet_create_args: {} subnet_cidr_start: "1.1.0.0/30" subnets_per_network: 2 - router_create_args: {} router_update_args: admin_state_up: False - name: "_router_updated" runner: type: "constant" times: 10 diff --git a/samples/tasks/scenarios/neutron/create-and-update-subnets.json b/samples/tasks/scenarios/neutron/create-and-update-subnets.json index 267b7e44..26e71327 100644 --- a/samples/tasks/scenarios/neutron/create-and-update-subnets.json +++ b/samples/tasks/scenarios/neutron/create-and-update-subnets.json @@ -3,11 +3,8 @@ { "args": { "subnet_update_args": { - "enable_dhcp": false, - "name": "_subnet_updated" + "enable_dhcp": false }, - "network_create_args": {}, - "subnet_create_args": {}, "subnet_cidr_start": "1.4.0.0/16", "subnets_per_network": 2 }, diff --git a/samples/tasks/scenarios/neutron/create-and-update-subnets.yaml b/samples/tasks/scenarios/neutron/create-and-update-subnets.yaml index d9d43771..6be020ae 100644 --- a/samples/tasks/scenarios/neutron/create-and-update-subnets.yaml +++ b/samples/tasks/scenarios/neutron/create-and-update-subnets.yaml @@ -2,13 +2,10 @@ NeutronNetworks.create_and_update_subnets: - args: - network_create_args: {} - subnet_create_args: {} subnet_cidr_start: "1.4.0.0/16" subnets_per_network: 2 subnet_update_args: enable_dhcp: False - name: "_subnet_updated" runner: type: "constant" times: 10 diff --git a/tasks/openstack/scenario/neutron.yaml b/tasks/openstack/scenario/neutron.yaml index c76d38b7..89e48d05 100644 --- a/tasks/openstack/scenario/neutron.yaml +++ b/tasks/openstack/scenario/neutron.yaml @@ -151,7 +151,6 @@ network_create_args: {} network_update_args: admin_state_up: false - name: "_updated" context: {% call user_context(tenants_amount, users_amount, use_existing_users) %} quotas: @@ -172,7 +171,6 @@ admin_state_up: false device_id: "dummy_id" device_owner: "dummy_owner" - name: "_port_updated" ports_per_network: 1 context: {% call user_context(tenants_amount, users_amount, use_existing_users) %} @@ -193,7 +191,6 @@ router_create_args: {} router_update_args: admin_state_up: false - name: "_router_updated" subnet_cidr_start: "1.1.0.0/30" subnet_create_args: {} subnets_per_network: 1 @@ -219,7 +216,6 @@ subnet_create_args: {} subnet_update_args: enable_dhcp: false - name: "_subnet_updated" subnets_per_network: 1 context: {% call user_context(tenants_amount, users_amount, use_existing_users) %} diff --git a/tests/ci/cover.sh b/tests/ci/cover.sh index 7ad96b8b..11096805 100755 --- a/tests/ci/cover.sh +++ b/tests/ci/cover.sh @@ -15,7 +15,7 @@ # License for the specific language governing permissions and limitations # under the License. -ALLOWED_EXTRA_MISSING=4 +ALLOWED_EXTRA_MISSING=10 show_diff () { head -1 $1 diff --git a/tests/unit/common/wrappers/test_network.py b/tests/unit/common/wrappers/test_network.py index 2e3860d1..e4bb92fc 100644 --- a/tests/unit/common/wrappers/test_network.py +++ b/tests/unit/common/wrappers/test_network.py @@ -38,9 +38,10 @@ class NeutronWrapperTestCase(test.TestCase): super(NeutronWrapperTestCase, self).setUp() self.owner = Owner() self.owner.generate_random_name = mock.Mock() - self.wrapper = network.NeutronWrapper(mock.MagicMock(), - self.owner, - config={}) + clients = mock.MagicMock() + clients.credential.permission = consts.EndpointPermission.ADMIN + self.wrapper = network.NeutronWrapper( + clients, self.owner, config={}) self._nc = self.wrapper.neutron.client def test_SUBNET_IP_VERSION(self): diff --git a/tests/unit/task/contexts/keystone/test_users.py b/tests/unit/task/contexts/keystone/test_users.py index a3365bc4..796e39f2 100644 --- a/tests/unit/task/contexts/keystone/test_users.py +++ b/tests/unit/task/contexts/keystone/test_users.py @@ -263,84 +263,60 @@ class UserGeneratorForNewUsersTestCase(test.ScenarioTestCase): "task": {"uuid": "task_id", "deployment_uuid": "dep_uuid"} }) - @mock.patch("%s.network.wrap" % CTX) - def test__remove_default_security_group_not_needed(self, mock_wrap): - services = {"compute": consts.Service.NOVA} - self.osclients.Clients().services.return_value = services - user_generator = users.UserGenerator(self.context) - user_generator._remove_default_security_group() - self.assertFalse(mock_wrap.called) + def test__remove_default_security_group(self): - @mock.patch("%s.network.wrap" % CTX) - def test__remove_default_security_group_neutron_no_sg(self, mock_wrap): - net_wrapper = mock.Mock(SERVICE_IMPL=consts.Service.NEUTRON) - net_wrapper.supports_extension.return_value = (False, None) - mock_wrap.return_value = net_wrapper - - user_generator = users.UserGenerator(self.context) - - admin_clients = mock.Mock() - admin_clients.services.return_value = { - "compute": consts.Service.NOVA, - "neutron": consts.Service.NEUTRON} - user_clients = [mock.Mock(), mock.Mock()] - self.osclients.Clients.side_effect = [admin_clients] + user_clients - - user_generator._remove_default_security_group() - - mock_wrap.assert_called_once_with(admin_clients, user_generator) - net_wrapper.supports_extension.assert_called_once_with( - "security-group") - - @mock.patch("%s.network" % CTX) - def test__remove_default_security_group(self, mock_network): - net_wrapper = mock.Mock(SERVICE_IMPL=consts.Service.NEUTRON) - net_wrapper.supports_extension.return_value = (True, None) - mock_network.wrap.return_value = net_wrapper - - user_generator = users.UserGenerator(self.context) - - admin_clients = mock.Mock() - admin_clients.services.return_value = { - "compute": consts.Service.NOVA, - "neutron": consts.Service.NEUTRON} - user1 = mock.Mock() - user1.neutron.return_value.list_security_groups.return_value = { - "security_groups": [{"id": "id-1", "name": "default"}, - {"id": "id-2", "name": "not-default"}]} - user2 = mock.Mock() - user2.neutron.return_value.list_security_groups.return_value = { - "security_groups": [{"id": "id-3", "name": "default"}, - {"id": "id-4", "name": "not-default"}]} - user_clients = [user1, user2] - self.osclients.Clients.side_effect = [admin_clients] + user_clients - - user_generator._iterate_per_tenants = mock.MagicMock( - return_value=[ - (mock.MagicMock(), "t1"), - (mock.MagicMock(), "t2") - ] + self.context.update( + tenants={ + "tenant-1": {}, + "tenant-2": {} + } ) - user_generator._remove_default_security_group() + self.osclients.Clients.return_value = mock.Mock() + neutron = self.osclients.Clients.return_value.neutron.return_value + neutron.list_extensions.return_value = { + "extensions": [{"alias": "security-group"}]} - mock_network.wrap.assert_called_once_with(admin_clients, - user_generator) + neutron.list_security_groups.return_value = { + "security_groups": [ + {"id": "id-1", "name": "default", "tenant_id": "tenant-1"}, + {"id": "id-2", "name": "default", "tenant_id": "tenant-2"}, + {"id": "id-3", "name": "default", "tenant_id": "tenant-3"} + ] + } - user_generator._iterate_per_tenants.assert_called_once_with() - expected = [mock.call(user_generator.credential)] + [ - mock.call(u["credential"]) - for u, t in user_generator._iterate_per_tenants.return_value] - self.osclients.Clients.assert_has_calls(expected, any_order=True) + users.UserGenerator(self.context)._remove_default_security_group() - user_net = user1.neutron.return_value - user_net.list_security_groups.assert_called_once_with(tenant_id="t1") - user_net = user2.neutron.return_value - user_net.list_security_groups.assert_called_once_with(tenant_id="t2") - admin_neutron = admin_clients.neutron.return_value + neutron.list_security_groups.assert_called_once_with(name="default") self.assertEqual( - [mock.call("id-1"), mock.call("id-3")], - admin_neutron.delete_security_group.call_args_list) + [mock.call("id-1"), mock.call("id-2")], + neutron.delete_security_group.call_args_list + ) + + def test__remove_default_security_group_no_sg(self): + self.context.update( + tenants={ + "tenant-1": {}, + "tenant-2": {} + } + ) + + self.osclients.Clients.return_value = mock.Mock() + neutron = self.osclients.Clients.return_value.neutron.return_value + neutron.list_extensions.return_value = {"extensions": []} + + neutron.list_security_groups.return_value = { + "security_groups": [ + {"id": "id-1", "name": "default", "tenant_id": "tenant-1"}, + {"id": "id-2", "name": "default", "tenant_id": "tenant-2"}, + {"id": "id-3", "name": "default", "tenant_id": "tenant-3"} + ] + } + + users.UserGenerator(self.context)._remove_default_security_group() + + self.assertFalse(neutron.list_security_groups.called) + self.assertFalse(neutron.delete_security_group.called) @mock.patch("%s.identity" % CTX) def test__create_tenants(self, mock_identity): diff --git a/tests/unit/task/contexts/network/test_allow_ssh.py b/tests/unit/task/contexts/network/test_allow_ssh.py index 11edc212..ace704cf 100644 --- a/tests/unit/task/contexts/network/test_allow_ssh.py +++ b/tests/unit/task/contexts/network/test_allow_ssh.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +import copy from unittest import mock from rally_openstack.task.contexts.network import allow_ssh @@ -26,87 +27,94 @@ class AllowSSHContextTestCase(test.TestCase): def setUp(self): super(AllowSSHContextTestCase, self).setUp() - self.users = 2 - self.secgroup_name = "test-secgroup" + self.users_count = 3 - self.ctx_with_secgroup = test.get_test_context() - self.ctx_with_secgroup.update({ - "users": [ + self.ctx = test.get_test_context() + self.ctx.update( + users=[ { - "tenant_id": "uuid1", - "credential": "credential", - "secgroup": {"id": "secgroup_id", "name": "secgroup"} + "tenant_id": f"uuid{i // 3}", + "credential": mock.MagicMock() } - ] * self.users, - "admin": {"tenant_id": "uuid2", "credential": "admin_credential"}, - "tenants": {"uuid1": {"id": "uuid1", "name": "uuid1"}}, - }) - self.ctx_without_secgroup = test.get_test_context() - self.ctx_without_secgroup.update({ - "users": [{"tenant_id": "uuid1", - "credential": "credential"}, - {"tenant_id": "uuid1", - "credential": "credential"}], - "admin": {"tenant_id": "uuid2", "credential": "admin_credential"}, - "tenants": {"uuid1": {"id": "uuid1", "name": "uuid1"}}, - }) - - @mock.patch("%s.osclients.Clients" % CTX) - def test__prepare_open_secgroup_rules(self, mock_clients): - fake_neutron = mock_clients.return_value.neutron.return_value - fake_neutron.list_security_groups.return_value = { - "security_groups": [{"id": "id", "name": "foo", - "security_group_rules": []}]} - - allow_ssh._prepare_open_secgroup("credential", self.secgroup_name) - allow_ssh._prepare_open_secgroup("credential", "foo") - - @mock.patch("%s.osclients.Clients" % CTX) - @mock.patch("%s._prepare_open_secgroup" % CTX) - @mock.patch("rally_openstack.common.wrappers.network.wrap") - def test_secgroup_setup_cleanup_with_secgroup_supported( - self, mock_network_wrap, mock__prepare_open_secgroup, - mock_clients): - mock_network_wrapper = mock.MagicMock() - mock_network_wrapper.supports_extension.return_value = (True, "") - mock_network_wrap.return_value = mock_network_wrapper - mock__prepare_open_secgroup.return_value = { - "name": "secgroup", - "id": "secgroup_id"} - mock_clients.return_value = mock.MagicMock() - - secgrp_ctx = allow_ssh.AllowSSH(self.ctx_with_secgroup) - secgrp_ctx.setup() - self.assertEqual(self.ctx_with_secgroup, secgrp_ctx.context) - secgrp_ctx.cleanup() - - self.assertEqual( - [ - mock.call("admin_credential"), - mock.call("credential"), - mock.call().neutron(), - mock.call().neutron().delete_security_group("secgroup_id") + for i in range(1, self.users_count + 1) ], - mock_clients.mock_calls) + admin={ + "tenant_id": "uuid2", + "credential": mock.MagicMock()}, + tenants={ + "uuid1": {"id": "uuid1", "name": "uuid1"}, + "uuid2": {"id": "uuid2", "name": "uuid1"} + } + ) - mock_network_wrap.assert_called_once_with( - mock_clients.return_value, secgrp_ctx, config={}) + def test_setup(self): + for i, user in enumerate(self.ctx["users"]): + clients = user["credential"].clients.return_value + nc = clients.neutron.return_value + nc.list_extensions.return_value = { + "extensions": [{"alias": "security-group"}] + } + nc.create_security_group.return_value = { + "security_group": { + "name": "xxx", + "id": f"security-group-{i}", + "security_group_rules": [] + } + } - @mock.patch("%s.osclients.Clients" % CTX) - @mock.patch("rally_openstack.common.wrappers.network.wrap") - def test_secgroup_setup_with_secgroup_unsupported( - self, mock_network_wrap, mock_clients): - mock_network_wrapper = mock.MagicMock() - mock_network_wrapper.supports_extension.return_value = ( - False, "Not supported") - mock_network_wrap.return_value = mock_network_wrapper - mock_clients.return_value = mock.MagicMock() + allow_ssh.AllowSSH(self.ctx).setup() - secgrp_ctx = allow_ssh.AllowSSH(dict(self.ctx_without_secgroup)) - secgrp_ctx.setup() - self.assertEqual(self.ctx_without_secgroup, secgrp_ctx.context) + # admin user should not be used + self.assertFalse(self.ctx["admin"]["credential"].clients.called) - mock_clients.assert_called_once_with("admin_credential") + processed_tenants = {} + for i, user in enumerate(self.ctx["users"]): + clients = user["credential"].clients.return_value + nc = clients.neutron.return_value + if i == 0: + nc.list_extensions.assert_called_once_with() + else: + self.assertFalse(nc.list_extensions.called) - mock_network_wrap.assert_called_once_with( - mock_clients.return_value, secgrp_ctx, config={}) + if user["tenant_id"] in processed_tenants: + self.assertFalse(nc.create_security_group.called) + self.assertFalse(nc.create_security_group_rule.called) + else: + nc.create_security_group.assert_called_once_with({ + "security_group": { + "name": mock.ANY, + "description": mock.ANY + } + }) + secgroup = nc.create_security_group.return_value + secgroup = secgroup["security_group"] + + rules = copy.deepcopy(allow_ssh._RULES_TO_ADD) + for rule in rules: + rule["security_group_id"] = secgroup["id"] + self.assertEqual( + [mock.call({"security_group_rule": rule}) + for rule in rules], + nc.create_security_group_rule.call_args_list + ) + + processed_tenants[user["tenant_id"]] = secgroup + + self.assertEqual(processed_tenants[user["tenant_id"]]["id"], + user["secgroup"]["id"]) + + def test_setup_no_security_group_extension(self): + clients = self.ctx["users"][0]["credential"].clients.return_value + nc = clients.neutron.return_value + nc.list_extensions.return_value = {"extensions": []} + + allow_ssh.AllowSSH(self.ctx).setup() + + # admin user should not be used + self.assertFalse(self.ctx["admin"]["credential"].clients.called) + + nc.list_extensions.assert_called_once_with() + for i, user in enumerate(self.ctx["users"]): + if i == 0: + continue + self.assertFalse(user["credential"].clients.called) diff --git a/tests/unit/task/contexts/network/test_network.py b/tests/unit/task/contexts/network/test_network.py index a579fd0d..0cca5327 100644 --- a/tests/unit/task/contexts/network/test_network.py +++ b/tests/unit/task/contexts/network/test_network.py @@ -21,7 +21,7 @@ import netaddr from rally_openstack.task.contexts.network import networks as network_context from tests.unit import test -NET = "rally_openstack.common.wrappers.network." +PATH = "rally_openstack.task.contexts.network.networks" @ddt.ddt @@ -30,26 +30,23 @@ class NetworkTestCase(test.TestCase): return {"task": {"uuid": "foo_task"}, "admin": {"credential": "foo_admin"}, "config": {"network": kwargs}, - "users": [{"id": "foo_user", "tenant_id": "foo_tenant"}, - {"id": "bar_user", "tenant_id": "bar_tenant"}], + "users": [{"id": "foo_user", "tenant_id": "foo_tenant", + "credential": mock.MagicMock()}, + {"id": "bar_user", "tenant_id": "bar_tenant", + "credential": mock.MagicMock()}], "tenants": {"foo_tenant": {"networks": [{"id": "foo_net"}]}, "bar_tenant": {"networks": [{"id": "bar_net"}]}}} - def test_START_CIDR_DFLT(self): + def test_default_start_cidr_is_valid(self): netaddr.IPNetwork(network_context.Network.DEFAULT_CONFIG["start_cidr"]) - @mock.patch("rally_openstack.common.osclients.Clients") - @mock.patch(NET + "wrap", return_value="foo_service") - def test__init__default(self, mock_wrap, mock_clients): + def test__init__default(self): context = network_context.Network(self.get_context()) self.assertEqual(1, context.config["networks_per_tenant"]) self.assertEqual(network_context.Network.DEFAULT_CONFIG["start_cidr"], context.config["start_cidr"]) - self.assertIsNone(context.config["dns_nameservers"]) - @mock.patch("rally_openstack.common.osclients.Clients") - @mock.patch(NET + "wrap", return_value="foo_service") - def test__init__explicit(self, mock_wrap, mock_clients): + def test__init__explicit(self): context = network_context.Network( self.get_context(start_cidr="foo_cidr", networks_per_tenant=42, network_create_args={"fakearg": "fake"}, @@ -61,57 +58,120 @@ class NetworkTestCase(test.TestCase): self.assertEqual(("1.2.3.4", "5.6.7.8"), context.config["dns_nameservers"]) - @ddt.data({}, - {"dns_nameservers": []}, - {"dns_nameservers": ["1.2.3.4", "5.6.7.8"]}) - @ddt.unpack - @mock.patch(NET + "wrap") - @mock.patch("rally_openstack.common.osclients.Clients") - def test_setup(self, mock_clients, mock_wrap, **dns_kwargs): - def create_net_infra(t_id, **kwargs): - return {"network": f"{t_id}-net", "subnets": []} + def test_setup(self): + ctx = self.get_context(networks_per_tenant=1, + network_create_args={}, + subnets_per_network=2, + dns_nameservers=None, + external=True) + user = ctx["users"][0] + nc = user["credential"].clients.return_value.neutron.return_value + network = {"id": "net-id", "name": "s-1"} + subnets = [ + {"id": "subnet1-id", "name": "subnet1-name"}, + {"id": "subnet2-id", "name": "subnet2-name"} + ] + router = {"id": "router"} + nc.create_network.return_value = {"network": network.copy()} + nc.create_router.return_value = {"router": router.copy()} + nc.create_subnet.side_effect = [{"subnet": s} for s in subnets] - mock_create = mock.Mock(side_effect=create_net_infra) - mock_wrap.return_value = mock.Mock( - _create_network_infrastructure=mock_create) - nets_per_tenant = 2 - net_context = network_context.Network( - self.get_context(networks_per_tenant=nets_per_tenant, - network_create_args={"fakearg": "fake"}, - **dns_kwargs)) - net_context._iterate_per_tenants = mock.MagicMock( - return_value=[ - ("foo_user", "foo_tenant"), - ("bar_user", "bar_tenant")] + network_context.Network(ctx).setup() + + ctx_data = ctx["tenants"][ctx["users"][0]["tenant_id"]] + self.assertEqual( + [{ + "id": network["id"], + "name": network["name"], + "router_id": router["id"], + "subnets": [s["id"] for s in subnets] + }], + ctx_data["networks"] ) - net_context.setup() + nc.create_network.assert_called_once_with( + {"network": {"name": mock.ANY}}) + nc.create_router.assert_called_once_with( + {"router": {"name": mock.ANY}}) + self.assertEqual( + [ + mock.call({"subnet": { + "name": mock.ANY, "network_id": network["id"], + "dns_nameservers": mock.ANY, + "ip_version": 4, + "cidr": mock.ANY}}) + for i in range(2)], + nc.create_subnet.call_args_list + ) + self.assertEqual( + [ + mock.call(router["id"], {"subnet_id": subnets[0]["id"]}), + mock.call(router["id"], {"subnet_id": subnets[1]["id"]}) + ], + nc.add_interface_router.call_args_list + ) - if "dns_nameservers" in dns_kwargs: - dns_kwargs["dns_nameservers"] = tuple( - dns_kwargs["dns_nameservers"]) - create_calls = [ - mock.call(tenant, dualstack=False, - subnets_num=1, network_create_args={"fakearg": "fake"}, - router_create_args={"external": True}, - **dns_kwargs) - for user, tenant in net_context._iterate_per_tenants.return_value] - mock_create.assert_has_calls(create_calls) + def test_setup_without_router(self): + dns_nameservers = ["1.2.3.4", "5.6.7.8"] + ctx = self.get_context(networks_per_tenant=1, + network_create_args={}, + subnets_per_network=2, + router=None, + dns_nameservers=dns_nameservers) + user = ctx["users"][0] + nc = user["credential"].clients.return_value.neutron.return_value + network = {"id": "net-id", "name": "s-1"} + subnets = [ + {"id": "subnet1-id", "name": "subnet1-name"}, + {"id": "subnet2-id", "name": "subnet2-name"} + ] + router = {"id": "router"} + nc.create_network.return_value = {"network": network.copy()} + nc.create_router.return_value = {"router": router.copy()} + nc.create_subnet.side_effect = [{"subnet": s} for s in subnets] - net_context._iterate_per_tenants.assert_called_once_with() - expected_networks = ["bar_tenant-net", - "foo_tenant-net"] * nets_per_tenant - actual_networks = [] - for tenant_id, tenant_ctx in net_context.context["tenants"].items(): - actual_networks.extend(tenant_ctx["networks"]) - self.assertSequenceEqual(sorted(expected_networks), - sorted(actual_networks)) + network_context.Network(ctx).setup() - @mock.patch("rally_openstack.common.osclients.Clients") - @mock.patch(NET + "wrap") - def test_cleanup(self, mock_wrap, mock_clients): - net_context = network_context.Network(self.get_context()) - net_context.cleanup() - mock_wrap().delete_network.assert_has_calls( - [mock.call({"id": "foo_net"}), mock.call({"id": "bar_net"})], - any_order=True) + ctx_data = ctx["tenants"][ctx["users"][0]["tenant_id"]] + self.assertEqual( + [{ + "id": network["id"], + "name": network["name"], + "router_id": None, + "subnets": [s["id"] for s in subnets] + }], + ctx_data["networks"] + ) + + nc.create_network.assert_called_once_with( + {"network": {"name": mock.ANY}}) + self.assertEqual( + [ + mock.call({"subnet": { + "name": mock.ANY, "network_id": network["id"], + # rally.task.context.Context converts list to unchangeable + # collection - tuple + "dns_nameservers": tuple(dns_nameservers), + "ip_version": 4, + "cidr": mock.ANY}}) + for i in range(2)], + nc.create_subnet.call_args_list + ) + + self.assertFalse(nc.create_router.called) + self.assertFalse(nc.add_interface_router.called) + + @mock.patch("%s.resource_manager.cleanup" % PATH) + def test_cleanup(self, mock_cleanup): + ctx = self.get_context() + + network_context.Network(ctx).cleanup() + + mock_cleanup.assert_called_once_with( + names=["neutron.subnet", "neutron.network", "neutron.router", + "neutron.port"], + superclass=network_context.Network, + admin=ctx.get("admin"), + users=ctx.get("users", []), + task_id=ctx["task"]["uuid"] + ) diff --git a/tests/unit/task/scenarios/neutron/test_network.py b/tests/unit/task/scenarios/neutron/test_network.py index c8a6ab6d..11c161b3 100644 --- a/tests/unit/task/scenarios/neutron/test_network.py +++ b/tests/unit/task/scenarios/neutron/test_network.py @@ -17,7 +17,6 @@ from unittest import mock import ddt -from rally import exceptions as rally_exceptions from rally_openstack.task.scenarios.neutron import network from tests.unit import test @@ -25,139 +24,179 @@ BASE = "rally_openstack.task.scenarios.neutron.network" @ddt.ddt -class NeutronNetworksTestCase(test.ScenarioTestCase): +class NeutronNetworksTestCase(test.TestCase): + def setUp(self): + super(NeutronNetworksTestCase, self).setUp() + patch = mock.patch("rally_openstack.common.osclients.Clients") + self.clients = patch.start().return_value + self.addCleanup(patch.stop) + + self.nc = self.clients.neutron.return_value + self.context = self.get_test_context() + + @staticmethod + def get_test_context(): + ctx = test.get_test_context() + ctx.update( + user_choice_method="random", + tenants={"tenant-1": {}}, + users=[ + { + "tenant_id": "tenant-1", + "credential": {} + } + ] + ) + return ctx @ddt.data( {"network_create_args": {}}, - {"network_create_args": {"name": "given-name"}}, + {"network_create_args": {"admin_state_up": False}}, {"network_create_args": {"provider:network_type": "vxlan"}} ) @ddt.unpack - @mock.patch("%s.CreateAndListNetworks._list_networks" % BASE) - @mock.patch("%s.CreateAndListNetworks._create_network" % BASE) - def test_create_and_list_networks(self, - mock__create_network, - mock__list_networks, - network_create_args): + def test_create_and_list_networks(self, network_create_args): + net = { + "id": "network-id", + "name": "network-name", + "admin_state_up": False + } + self.nc.create_network.return_value = {"network": net} + scenario = network.CreateAndListNetworks(self.context) - scenario.run(network_create_args=network_create_args) - mock__create_network.assert_called_once_with(network_create_args) - mock__list_networks.assert_called_once_with() - mock__create_network.reset_mock() - mock__list_networks.reset_mock() + self.nc.create_network.assert_called_once_with( + {"network": {"name": mock.ANY, **network_create_args}} + ) + self.nc.list_networks.assert_called_once_with() @ddt.data( {"network_create_args": {}}, - {"network_create_args": {"name": "given-name"}}, + {"network_create_args": {"admin_state_up": False}}, ) @ddt.unpack - @mock.patch("%s.CreateAndShowNetwork._show_network" % BASE) - @mock.patch("%s.CreateAndShowNetwork._create_network" % BASE) - def test_create_and_show_network(self, - mock__create_network, - mock__show_network, - network_create_args): - scenario = network.CreateAndShowNetwork(self.context) - mock_net = mock.Mock() + def test_create_and_show_network(self, network_create_args): + net = { + "id": "network-id", + "name": "network-name", + "admin_state_up": False + } + self.nc.create_network.return_value = {"network": net} + + scenario = network.CreateAndShowNetwork(self.context) - mock__create_network.return_value = mock_net scenario.run(network_create_args=network_create_args) - mock__create_network.assert_called_once_with(network_create_args) - mock__show_network.assert_called_once_with(mock_net) + self.nc.create_network.assert_called_once_with( + {"network": {"name": mock.ANY, **network_create_args}} + ) + self.nc.show_network.assert_called_once_with(net["id"]) - mock__create_network.reset_mock() - mock__show_network.reset_mock() + def test_create_and_update_networks(self): + net = { + "id": "network-id", + "name": "network-name", + "admin_state_up": False + } + self.nc.create_network.return_value = {"network": net} - @mock.patch("%s.CreateAndUpdateNetworks._update_network" % BASE) - @mock.patch("%s.CreateAndUpdateNetworks._create_network" % BASE, - return_value={ - "network": { - "id": "network-id", - "name": "network-name", - "admin_state_up": False - } - }) - def test_create_and_update_networks(self, - mock__create_network, - mock__update_network): scenario = network.CreateAndUpdateNetworks(self.context) - network_update_args = {"name": "_updated", "admin_state_up": True} + network_update_args = {"admin_state_up": True} # Default options scenario.run(network_update_args=network_update_args) - mock__create_network.assert_called_once_with({}) + self.nc.create_network.assert_called_once_with( + {"network": {"name": mock.ANY}} + ) + self.nc.update_network.assert_called_once_with( + net["id"], {"network": network_update_args} + ) - mock__update_network.assert_has_calls( - [mock.call( - mock__create_network.return_value, network_update_args - )]) + self.nc.create_network.reset_mock() + self.nc.update_network.reset_mock() - mock__create_network.reset_mock() - mock__update_network.reset_mock() - - # Explicit network name is specified + # admin_state_up is specified network_create_args = { - "name": "network-name", "admin_state_up": False } scenario.run(network_create_args=network_create_args, network_update_args=network_update_args) - mock__create_network.assert_called_once_with(network_create_args) - mock__update_network.assert_has_calls( - [mock.call(mock__create_network.return_value, - network_update_args)]) + self.nc.create_network.assert_called_once_with( + {"network": {"name": mock.ANY, **network_create_args}} + ) + self.nc.update_network.assert_called_once_with( + net["id"], {"network": network_update_args} + ) + + def test_create_and_delete_networks(self): + net = { + "id": "network-id", + "name": "network-name", + "admin_state_up": False + } + self.nc.create_network.return_value = {"network": net} - @mock.patch("%s.CreateAndDeleteNetworks._delete_network" % BASE) - @mock.patch("%s.CreateAndDeleteNetworks._create_network" % BASE) - def test_create_and_delete_networks(self, - mock__create_network, - mock__delete_network): scenario = network.CreateAndDeleteNetworks(self.context) # Default options network_create_args = {} - scenario.run() - mock__create_network.assert_called_once_with(network_create_args) - self.assertTrue(mock__delete_network.call_count) + scenario.run(network_create_args=network_create_args) + self.nc.create_network.assert_called_once_with( + {"network": {"name": mock.ANY}} + ) + self.assertTrue(self.nc.delete_network.called) - mock__create_network.reset_mock() - mock__delete_network.reset_mock() + self.nc.create_network.reset_mock() + self.nc.delete_network.reset_mock() # Explicit network name is specified - network_create_args = {"name": "given-name"} + network_create_args = {"admin_state_up": True} scenario.run(network_create_args=network_create_args) - mock__create_network.assert_called_once_with(network_create_args) - self.assertTrue(mock__delete_network.call_count) + + self.nc.create_network.assert_called_once_with( + {"network": {"name": mock.ANY, **network_create_args}} + ) + self.assertTrue(self.nc.delete_network.called) def test_create_and_list_subnets(self): network_create_args = {"router:external": True} subnet_create_args = {"allocation_pools": []} - subnet_cidr_start = "default_cidr" + subnet_cidr_start = "10.2.0.0/24" subnets_per_network = 5 net = mock.MagicMock() + self.nc.create_network.return_value = {"network": net} + self.nc.create_subnet.side_effect = [ + {"subnet": {"id": i}} for i in range(subnets_per_network) + ] + scenario = network.CreateAndListSubnets(self.context) - scenario._create_network = mock.Mock(return_value=net) - scenario._create_subnets = mock.Mock() - scenario._list_subnets = mock.Mock() scenario.run(network_create_args=network_create_args, subnet_create_args=subnet_create_args, subnet_cidr_start=subnet_cidr_start, subnets_per_network=subnets_per_network) - scenario._create_network.assert_called_once_with( - network_create_args) - scenario._create_subnets.assert_called_once_with( - net, subnet_create_args, subnet_cidr_start, subnets_per_network) + self.nc.create_network.assert_called_once_with( + {"network": {"name": mock.ANY, **network_create_args}} + ) + self.assertEqual( + [mock.call({"subnet": { + "name": mock.ANY, + "network_id": net["id"], + "dns_nameservers": ["8.8.8.8", "8.8.4.4"], + "ip_version": 4, + "cidr": mock.ANY, + **subnet_create_args}} + )] * subnets_per_network, + self.nc.create_subnet.call_args_list + ) - scenario._list_subnets.assert_called_once_with() + self.nc.list_subnets.assert_called_once_with() def test_create_and_show_subnets(self): network_create_args = {"router:external": True} @@ -166,10 +205,12 @@ class NeutronNetworksTestCase(test.ScenarioTestCase): subnets_per_network = 5 net = mock.MagicMock() + self.nc.create_subnet.side_effect = [ + {"subnet": {"id": i}} for i in range(subnets_per_network) + ] + scenario = network.CreateAndShowSubnets(self.context) scenario._get_or_create_network = mock.Mock(return_value=net) - scenario._create_subnets = mock.MagicMock() - scenario._show_subnet = mock.Mock() scenario.run(network_create_args=network_create_args, subnet_create_args=subnet_create_args, @@ -177,46 +218,68 @@ class NeutronNetworksTestCase(test.ScenarioTestCase): subnets_per_network=subnets_per_network) scenario._get_or_create_network.assert_called_once_with( - network_create_args) - scenario._create_subnets.assert_called_once_with( - net, subnet_create_args, subnet_cidr_start, subnets_per_network) - for subnet in scenario._create_subnets.return_value: - scenario._show_subnet.assert_called_with(subnet) + **network_create_args) + self.assertEqual( + [mock.call({"subnet": { + "name": mock.ANY, + "network_id": net["id"], + "dns_nameservers": ["8.8.8.8", "8.8.4.4"], + "ip_version": 4, + "cidr": mock.ANY, + **subnet_create_args}} + )] * subnets_per_network, + self.nc.create_subnet.call_args_list + ) + self.assertEqual( + [mock.call(i) for i in range(subnets_per_network)], + self.nc.show_subnet.call_args_list + ) def test_set_and_clear_router_gateway(self): network_create_args = {"router:external": True} router_create_args = {"admin_state_up": True} enable_snat = True - ext_net = mock.MagicMock() - router = mock.MagicMock() - scenario = network.SetAndClearRouterGateway(self.context) - scenario._create_network = mock.Mock(return_value=ext_net) - scenario._create_router = mock.Mock(return_value=router) - scenario._add_gateway_router = mock.Mock() - scenario._remove_gateway_router = mock.Mock() + ext_net = {"id": "ext-net-1"} + router = {"id": "router-id"} - scenario.run(enable_snat, network_create_args, router_create_args) + self.nc.create_network.return_value = {"network": ext_net} + self.nc.create_router.return_value = {"router": router} + self.nc.list_extensions.return_value = { + "extensions": [{"alias": "ext-gw-mode"}] + } - scenario._create_network.assert_called_once_with( - network_create_args) - scenario._create_router.assert_called_once_with(router_create_args) - scenario._add_gateway_router.assert_called_once_with(router, ext_net, - enable_snat) - scenario._remove_gateway_router.assert_called_once_with(router) + network.SetAndClearRouterGateway(self.context).run( + enable_snat, network_create_args, router_create_args + ) + + self.nc.create_network.assert_called_once_with( + {"network": {"name": mock.ANY, **network_create_args}} + ) + + self.nc.create_router.assert_called_once_with( + {"router": {"name": mock.ANY, **router_create_args}} + ) + + self.nc.add_gateway_router.assert_called_once_with( + router["id"], {"network_id": ext_net["id"], + "enable_snat": enable_snat} + ) + self.nc.remove_gateway_router.assert_called_once_with(router["id"]) def test_create_and_update_subnets(self): network_create_args = {"router:external": True} subnet_create_args = {"allocation_pools": []} - subnet_update_args = {"enabled_dhcp": True} - subnet_cidr_start = "default_cidr" + subnet_update_args = {"enable_dhcp": True} + subnet_cidr_start = "1.1.0.0/30" subnets_per_network = 5 net = mock.MagicMock() - subnets = [mock.MagicMock() for _ in range(subnets_per_network)] + + self.nc.create_network.return_value = {"network": net} + self.nc.create_subnet.side_effect = [ + {"subnet": {"id": i}} for i in range(subnets_per_network) + ] scenario = network.CreateAndUpdateSubnets(self.context) - scenario._create_network = mock.Mock(return_value=net) - scenario._create_subnets = mock.Mock(return_value=subnets) - scenario._update_subnet = mock.Mock() scenario.run(subnet_update_args, network_create_args=network_create_args, @@ -224,25 +287,39 @@ class NeutronNetworksTestCase(test.ScenarioTestCase): subnet_cidr_start=subnet_cidr_start, subnets_per_network=subnets_per_network) - scenario._create_network.assert_called_once_with( - network_create_args) - scenario._create_subnets.assert_called_once_with( - net, subnet_create_args, subnet_cidr_start, subnets_per_network) - scenario._update_subnet.assert_has_calls( - [mock.call(s, subnet_update_args) for s in subnets]) + self.nc.create_network.assert_called_once_with( + {"network": {"name": mock.ANY, **network_create_args}} + ) + self.assertEqual( + [mock.call({"subnet": { + "name": mock.ANY, + "network_id": net["id"], + "dns_nameservers": ["8.8.8.8", "8.8.4.4"], + "ip_version": 4, + "cidr": mock.ANY, + **subnet_create_args}} + )] * subnets_per_network, + self.nc.create_subnet.call_args_list + ) + self.assertEqual( + [mock.call(s, {"subnet": subnet_update_args}) + for s in range(subnets_per_network)], + self.nc.update_subnet.call_args_list + ) def test_create_and_delete_subnets(self): network_create_args = {"router:external": True} subnet_create_args = {"allocation_pools": []} - subnet_cidr_start = "default_cidr" + subnet_cidr_start = "1.1.0.0/30" subnets_per_network = 5 net = mock.MagicMock() - subnets = [mock.MagicMock() for _ in range(subnets_per_network)] + + self.nc.create_subnet.side_effect = [ + {"subnet": {"id": i}} for i in range(subnets_per_network) + ] scenario = network.CreateAndDeleteSubnets(self.context) scenario._get_or_create_network = mock.Mock(return_value=net) - scenario._create_subnets = mock.Mock(return_value=subnets) - scenario._delete_subnet = mock.Mock() scenario.run(network_create_args=network_create_args, subnet_create_args=subnet_create_args, @@ -250,60 +327,79 @@ class NeutronNetworksTestCase(test.ScenarioTestCase): subnets_per_network=subnets_per_network) scenario._get_or_create_network.assert_called_once_with( - network_create_args) - scenario._create_subnets.assert_called_once_with( - net, subnet_create_args, subnet_cidr_start, subnets_per_network) - scenario._delete_subnet.assert_has_calls( - [mock.call(s) for s in subnets]) + **network_create_args) + self.assertEqual( + [mock.call({"subnet": { + "name": mock.ANY, + "network_id": net["id"], + "dns_nameservers": ["8.8.8.8", "8.8.4.4"], + "ip_version": 4, + "cidr": mock.ANY, + **subnet_create_args}} + )] * subnets_per_network, + self.nc.create_subnet.call_args_list + ) + self.assertEqual( + [mock.call(s) for s in range(subnets_per_network)], + self.nc.delete_subnet.call_args_list + ) def test_create_and_list_routers(self): network_create_args = {"router:external": True} subnet_create_args = {"allocation_pools": []} - subnet_cidr_start = "default_cidr" + subnet_cidr_start = "1.1.0.0/30" subnets_per_network = 5 router_create_args = {"admin_state_up": True} + net = {"id": "foo"} + self.nc.create_network.return_value = {"network": net} scenario = network.CreateAndListRouters(self.context) - scenario._create_network_structure = mock.Mock() - scenario._list_routers = mock.Mock() scenario.run(network_create_args=network_create_args, subnet_create_args=subnet_create_args, subnet_cidr_start=subnet_cidr_start, subnets_per_network=subnets_per_network, router_create_args=router_create_args) - - scenario._create_network_structure.assert_called_once_with( - network_create_args, subnet_create_args, subnet_cidr_start, - subnets_per_network, router_create_args) - scenario._list_routers.assert_called_once_with() - - def test_list_agents(self): - agent_args = { - "F": "id", - "sort-dir": "asc" - } - scenario = network.ListAgents(self.context) - scenario._list_agents = mock.Mock() - - scenario.run(agent_args=agent_args) - scenario._list_agents.assert_called_once_with(**agent_args) + self.nc.create_network.assert_called_once_with( + {"network": {"name": mock.ANY, **network_create_args}} + ) + self.assertEqual( + [mock.call({"subnet": { + "name": mock.ANY, + "network_id": net["id"], + "dns_nameservers": ["8.8.8.8", "8.8.4.4"], + "ip_version": 4, + "cidr": mock.ANY, + **subnet_create_args}} + )] * subnets_per_network, + self.nc.create_subnet.call_args_list + ) + self.assertEqual( + [mock.call({"router": { + "name": mock.ANY, + **router_create_args}} + )] * subnets_per_network, + self.nc.create_router.call_args_list + ) + self.nc.list_routers.assert_called_once_with() def test_create_and_update_routers(self): router_update_args = {"admin_state_up": False} network_create_args = {"router:external": True} subnet_create_args = {"allocation_pools": []} - subnet_cidr_start = "default_cidr" + subnet_cidr_start = "1.1.0.0/30" subnets_per_network = 5 router_create_args = {"admin_state_up": True} - net = mock.MagicMock() - subnets = [mock.MagicMock() for i in range(subnets_per_network)] - routers = [mock.MagicMock() for i in range(subnets_per_network)] + net = {"id": "foo"} + self.nc.create_network.return_value = {"network": net} + self.nc.create_subnet.side_effect = [ + {"subnet": {"id": i}} for i in range(subnets_per_network) + ] + self.nc.create_router.side_effect = [ + {"router": {"id": i}} for i in range(subnets_per_network) + ] scenario = network.CreateAndUpdateRouters(self.context) - scenario._create_network_structure = mock.Mock( - return_value=(net, subnets, routers)) - scenario._update_router = mock.Mock() scenario.run(router_update_args, network_create_args=network_create_args, @@ -312,29 +408,49 @@ class NeutronNetworksTestCase(test.ScenarioTestCase): subnets_per_network=subnets_per_network, router_create_args=router_create_args) - scenario._create_network_structure.assert_called_once_with( - network_create_args, subnet_create_args, subnet_cidr_start, - subnets_per_network, router_create_args) - - update_calls = [mock.call(router, router_update_args) - for router in routers] - scenario._update_router.assert_has_calls(update_calls) + self.nc.create_network.assert_called_once_with( + {"network": {"name": mock.ANY, **network_create_args}} + ) + self.assertEqual( + [mock.call({"subnet": { + "name": mock.ANY, + "network_id": net["id"], + "dns_nameservers": ["8.8.8.8", "8.8.4.4"], + "ip_version": 4, + "cidr": mock.ANY, + **subnet_create_args}} + )] * subnets_per_network, + self.nc.create_subnet.call_args_list + ) + self.assertEqual( + [mock.call({"router": { + "name": mock.ANY, + **router_create_args}} + )] * subnets_per_network, + self.nc.create_router.call_args_list + ) + self.assertEqual( + [mock.call(i, {"router": router_update_args}) + for i in range(subnets_per_network)], + self.nc.update_router.call_args_list + ) def test_create_and_delete_routers(self): network_create_args = {"router:external": True} subnet_create_args = {"allocation_pools": []} - subnet_cidr_start = "default_cidr" + subnet_cidr_start = "1.1.0.0/30" subnets_per_network = 5 router_create_args = {"admin_state_up": True} - net = mock.MagicMock() - subnets = [mock.MagicMock() for i in range(subnets_per_network)] - routers = [mock.MagicMock() for i in range(subnets_per_network)] + net = {"id": "foo"} + self.nc.create_network.return_value = {"network": net} + self.nc.create_subnet.side_effect = [ + {"subnet": {"id": f"s-{i}"}} for i in range(subnets_per_network) + ] + self.nc.create_router.side_effect = [ + {"router": {"id": f"r-{i}"}} for i in range(subnets_per_network) + ] scenario = network.CreateAndDeleteRouters(self.context) - scenario._create_network_structure = mock.Mock( - return_value=(net, subnets, routers)) - scenario._remove_interface_router = mock.Mock() - scenario._delete_router = mock.Mock() scenario.run(network_create_args=network_create_args, subnet_create_args=subnet_create_args, @@ -342,30 +458,53 @@ class NeutronNetworksTestCase(test.ScenarioTestCase): subnets_per_network=subnets_per_network, router_create_args=router_create_args) - scenario._create_network_structure.assert_called_once_with( - network_create_args, subnet_create_args, subnet_cidr_start, - subnets_per_network, router_create_args) - - scenario._remove_interface_router.assert_has_calls([ - mock.call(subnets[i]["subnet"], routers[i]["router"]) - for i in range(subnets_per_network)]) - scenario._delete_router.assert_has_calls( - [mock.call(router) for router in routers]) + self.nc.create_network.assert_called_once_with( + {"network": {"name": mock.ANY, **network_create_args}} + ) + self.assertEqual( + [mock.call({"subnet": { + "name": mock.ANY, + "network_id": net["id"], + "dns_nameservers": ["8.8.8.8", "8.8.4.4"], + "ip_version": 4, + "cidr": mock.ANY, + **subnet_create_args}} + )] * subnets_per_network, + self.nc.create_subnet.call_args_list + ) + self.assertEqual( + [mock.call({"router": { + "name": mock.ANY, + **router_create_args}} + )] * subnets_per_network, + self.nc.create_router.call_args_list + ) + self.assertEqual( + [mock.call(f"r-{i}", {"subnet_id": f"s-{i}"}) + for i in range(subnets_per_network)], + self.nc.remove_interface_router.call_args_list + ) + self.assertEqual( + [mock.call(f"r-{i}") for i in range(subnets_per_network)], + self.nc.delete_router.call_args_list + ) def test_create_and_show_routers(self): network_create_args = {"router:external": True} subnet_create_args = {"allocation_pools": []} - subnet_cidr_start = "default_cidr" + subnet_cidr_start = "1.1.0.0/30" subnets_per_network = 5 router_create_args = {"admin_state_up": True} - net = mock.MagicMock() - subnets = [mock.MagicMock() for i in range(subnets_per_network)] - routers = [mock.MagicMock() for i in range(subnets_per_network)] + net = {"id": "foo"} + self.nc.create_network.return_value = {"network": net} + self.nc.create_subnet.side_effect = [ + {"subnet": {"id": i}} for i in range(subnets_per_network) + ] + self.nc.create_router.side_effect = [ + {"router": {"id": i}} for i in range(subnets_per_network) + ] scenario = network.CreateAndShowRouters(self.context) - scenario._create_network_structure = mock.Mock( - return_value=(net, subnets, routers)) - scenario._show_router = mock.Mock() scenario.run(network_create_args=network_create_args, subnet_create_args=subnet_create_args, @@ -373,12 +512,41 @@ class NeutronNetworksTestCase(test.ScenarioTestCase): subnets_per_network=subnets_per_network, router_create_args=router_create_args) - scenario._create_network_structure.assert_called_once_with( - network_create_args, subnet_create_args, subnet_cidr_start, - subnets_per_network, router_create_args) + self.nc.create_network.assert_called_once_with( + {"network": {"name": mock.ANY, **network_create_args}} + ) + self.assertEqual( + [mock.call({"subnet": { + "name": mock.ANY, + "network_id": net["id"], + "dns_nameservers": ["8.8.8.8", "8.8.4.4"], + "ip_version": 4, + "cidr": mock.ANY, + **subnet_create_args}} + )] * subnets_per_network, + self.nc.create_subnet.call_args_list + ) + self.assertEqual( + [mock.call({"router": { + "name": mock.ANY, + **router_create_args}} + )] * subnets_per_network, + self.nc.create_router.call_args_list + ) + self.assertEqual( + [mock.call(i) for i in range(subnets_per_network)], + self.nc.show_router.call_args_list + ) - scenario._show_router.assert_has_calls( - [mock.call(router) for router in routers]) + def test_list_agents(self): + agent_args = { + "F": "id", + "sort-dir": "asc" + } + scenario = network.ListAgents(self.context) + + scenario.run(agent_args=agent_args) + self.nc.list_agents.assert_called_once_with(**agent_args) def test_create_and_list_ports(self): port_create_args = {"allocation_pools": []} @@ -388,60 +556,76 @@ class NeutronNetworksTestCase(test.ScenarioTestCase): scenario = network.CreateAndListPorts(self.context) scenario._get_or_create_network = mock.Mock(return_value=net) - scenario._create_port = mock.MagicMock() - scenario._list_ports = mock.Mock() scenario.run(network_create_args=network_create_args, port_create_args=port_create_args, ports_per_network=ports_per_network) scenario._get_or_create_network.assert_called_once_with( - network_create_args) - scenario._create_port.assert_has_calls( - [mock.call(net, port_create_args) - for _ in range(ports_per_network)]) + **network_create_args) + self.assertEqual( + [ + mock.call({ + "port": { + "network_id": net["id"], + "name": mock.ANY, + **port_create_args + } + }) for _ in range(ports_per_network) + ], + self.nc.create_port.call_args_list + ) - scenario._list_ports.assert_called_once_with() + self.nc.list_ports.assert_called_once_with() def test_create_and_update_ports(self): - port_update_args = {"admin_state_up": False}, + port_update_args = {"admin_state_up": False} port_create_args = {"allocation_pools": []} ports_per_network = 10 network_create_args = {"router:external": True} net = mock.MagicMock() - ports = [mock.MagicMock() for _ in range(ports_per_network)] + self.nc.create_port.side_effect = [ + {"port": {"id": f"p-{i}"}} + for i in range(ports_per_network) + ] scenario = network.CreateAndUpdatePorts(self.context) scenario._get_or_create_network = mock.Mock(return_value=net) - scenario._create_port = mock.Mock(side_effect=ports) - scenario._update_port = mock.Mock() scenario.run(port_update_args, network_create_args=network_create_args, port_create_args=port_create_args, ports_per_network=ports_per_network) + scenario._get_or_create_network.assert_called_once_with( - network_create_args) - scenario._create_port.assert_has_calls( - [mock.call(net, port_create_args) - for _ in range(ports_per_network)]) - scenario._update_port.assert_has_calls( - [mock.call(p, port_update_args) for p in ports]) + **network_create_args) + self.assertEqual( + [mock.call({"port": { + "network_id": net["id"], + "name": mock.ANY, + **port_create_args}} + )] * ports_per_network, + self.nc.create_port.call_args_list + ) + self.assertEqual( + [mock.call(f"p-{i}", {"port": port_update_args}) + for i in range(ports_per_network)], + self.nc.update_port.call_args_list + ) def test_create_and_bind_ports(self): ports_per_network = 2 - ports = [mock.Mock() for _ in range(ports_per_network)] port_update_args = { "device_owner": "compute:nova", "device_id": "ba805478-85ff-11e9-a2e4-2b8dea218fc8", "binding:host_id": "fake-host", } - - context = { - "tenant": {"id": "fake-tenant-id"}, + net = {"id": "net-id"} + self.context.update({ "tenants": { - "fake-tenant-id": { + "tenant-1": { + "id": "tenant-1", "networks": [ - mock.Mock() + net ], }, }, @@ -451,22 +635,31 @@ class NeutronNetworksTestCase(test.ScenarioTestCase): "admin_state_up": True, "agent_type": "Open vSwitch agent", }], - } - scenario = network.CreateAndBindPorts(context) + }) + scenario = network.CreateAndBindPorts(self.context) + scenario.admin_neutron = mock.MagicMock() - scenario._create_network = mock.Mock() - scenario._create_subnet = mock.Mock() - scenario._create_port = mock.Mock( - side_effect=ports) - scenario._update_port = mock.Mock() + self.nc.create_port.side_effect = [ + {"port": {"id": f"p-{i}"}} + for i in range(ports_per_network) + ] - scenario.run( - ports_per_network=ports_per_network) + scenario.run(ports_per_network=ports_per_network) - scenario._update_port.assert_has_calls( - [mock.call(p, port_update_args=port_update_args) for p in ports]) + self.assertEqual( + [mock.call({"port": { + "network_id": net["id"], + "name": mock.ANY}} + )] * ports_per_network, + self.nc.create_port.call_args_list + ) + self.assertEqual( + [mock.call(port_id=f"p-{i}", **port_update_args) + for i in range(ports_per_network)], + scenario.admin_neutron.update_port.call_args_list + ) - def test_create_and_show_ports_positive(self): + def test_create_and_show_ports(self): port_create_args = {"allocation_pools": []} ports_per_network = 1 network_create_args = {"router:external": True} @@ -474,151 +667,159 @@ class NeutronNetworksTestCase(test.ScenarioTestCase): scenario = network.CreateAndShowPorts(self.context) scenario._get_or_create_network = mock.MagicMock(return_value=net) - scenario._create_port = mock.MagicMock() - scenario._show_port = mock.MagicMock() - port = {"port": {"id": 1, "name": "f"}} - port_info = {"port": {"id": 1, "name": "f", "status": "ACTIVE"}} - scenario._show_port.return_value = port_info + port = {"id": 1, "name": "f"} + self.nc.create_port.return_value = {"port": port} - # Positive case: - scenario._create_port.return_value = port scenario.run(network_create_args=network_create_args, port_create_args=port_create_args, ports_per_network=ports_per_network) scenario._get_or_create_network.assert_called_once_with( - network_create_args) - scenario._create_port.assert_called_with(net, port_create_args) - scenario._show_port.assert_called_with(port) + **network_create_args) + self.nc.create_port.assert_called_with({"port": { + "network_id": net["id"], "name": mock.ANY, **port_create_args + }}) - def test_create_and_show_ports_negative(self): - port_create_args = {"allocation_pools": []} - ports_per_network = 1 - network_create_args = {"router:external": True} - net = mock.MagicMock() - - scenario = network.CreateAndShowPorts(self.context) - scenario._get_or_create_network = mock.MagicMock(return_value=net) - scenario._create_port = mock.MagicMock() - scenario._show_port = mock.MagicMock() - - # Negative case1: port isn't created - scenario._create_port.return_value = None - self.assertRaises(rally_exceptions.RallyAssertionError, - scenario.run, - network_create_args, - port_create_args, - ports_per_network) - scenario._get_or_create_network.assert_called_once_with( - network_create_args) - scenario._create_port.assert_called_once_with(net, port_create_args) - - # Negative case2: port isn't show - port = {"port": {"id": 1, "name": "f1"}} - port_info = {"port": {"id": 2, "name": "f2", "status": "ACTIVE"}} - scenario._show_port.return_value = port_info - scenario._create_port.return_value = port - - self.assertRaises(rally_exceptions.RallyAssertionError, - scenario.run, - network_create_args, - port_create_args, - ports_per_network) - - scenario._get_or_create_network.assert_called_with( - network_create_args) - scenario._create_port.assert_called_with(net, port_create_args) - scenario._show_port.assert_called_with(port) + self.nc.show_port.assert_called_with(port["id"]) def test_create_and_delete_ports(self): port_create_args = {"allocation_pools": []} ports_per_network = 10 network_create_args = {"router:external": True} net = mock.MagicMock() - ports = [mock.MagicMock() for _ in range(ports_per_network)] + self.nc.create_port.side_effect = [ + {"port": {"id": f"p-{i}"}} + for i in range(ports_per_network) + ] scenario = network.CreateAndDeletePorts(self.context) scenario._get_or_create_network = mock.Mock(return_value=net) - scenario._create_port = mock.Mock(side_effect=ports) - scenario._delete_port = mock.Mock() scenario.run(network_create_args=network_create_args, port_create_args=port_create_args, ports_per_network=ports_per_network) + scenario._get_or_create_network.assert_called_once_with( - network_create_args) - scenario._create_port.assert_has_calls( - [mock.call(net, port_create_args) - for _ in range(ports_per_network)]) - scenario._delete_port.assert_has_calls( - [mock.call(p) for p in ports]) + **network_create_args) + + self.assertEqual( + [mock.call({"port": { + "network_id": net["id"], + "name": mock.ANY, + **port_create_args}} + )] * ports_per_network, + self.nc.create_port.call_args_list + ) + self.assertEqual( + [mock.call(f"p-{i}") for i in range(ports_per_network)], + self.nc.delete_port.call_args_list + ) @ddt.data( - {"floating_network": "ext-net"}, - {"floating_network": "ext-net", - "floating_ip_args": {"floating_ip_address": "1.1.1.1"}}, + {}, + {"floating_ip_args": {"floating_ip_address": "1.1.1.1"}}, ) @ddt.unpack - def test_create_and_list_floating_ips(self, floating_network=None, - floating_ip_args=None): + def test_create_and_list_floating_ips(self, floating_ip_args=None): + floating_ip_args = floating_ip_args or {} + floating_network = {"id": "ext-net"} + scenario = network.CreateAndListFloatingIps(self.context) - floating_ip_args = floating_ip_args or {} - scenario._create_floatingip = mock.Mock() - scenario._list_floating_ips = mock.Mock() + + self.nc.create_floatingip.return_value = {"floatingip": mock.Mock()} + self.nc.list_floatingips.return_value = {"floatingips": mock.Mock()} scenario.run(floating_network=floating_network, floating_ip_args=floating_ip_args) - scenario._create_floatingip.assert_called_once_with( - floating_network, **floating_ip_args) - scenario._list_floating_ips.assert_called_once_with() + self.nc.create_floatingip.assert_called_once_with( + {"floatingip": {"description": mock.ANY, + "floating_network_id": floating_network["id"], + **floating_ip_args}}) + self.nc.list_floatingips.assert_called_once_with() @ddt.data( - {"floating_network": "ext-net"}, - {"floating_network": "ext-net", - "floating_ip_args": {"floating_ip_address": "1.1.1.1"}}, + {}, + {"floating_ip_args": {"floating_ip_address": "1.1.1.1"}}, ) @ddt.unpack - def test_create_and_delete_floating_ips(self, floating_network=None, - floating_ip_args=None): - scenario = network.CreateAndDeleteFloatingIps(self.context) + def test_create_and_delete_floating_ips(self, floating_ip_args=None): + floating_network = {"id": "ext-net"} floating_ip_args = floating_ip_args or {} - fip = {"floatingip": {"id": "floating-ip-id"}} - scenario._create_floatingip = mock.Mock(return_value=fip) - scenario._delete_floating_ip = mock.Mock() + floatingip = {"id": "floating-ip-id"} + + self.nc.create_floatingip.return_value = {"floatingip": floatingip} + + scenario = network.CreateAndDeleteFloatingIps(self.context) + scenario.run(floating_network=floating_network, floating_ip_args=floating_ip_args) - scenario._create_floatingip.assert_called_once_with( - floating_network, **floating_ip_args) - scenario._delete_floating_ip.assert_called_once_with( - scenario._create_floatingip.return_value["floatingip"]) + self.nc.create_floatingip.assert_called_once_with( + {"floatingip": {"description": mock.ANY, + "floating_network_id": floating_network["id"], + **floating_ip_args}}) + self.nc.delete_floatingip.assert_called_once_with(floatingip["id"]) def test_associate_and_dissociate_floating_ips(self): - scenario = network.AssociateAndDissociateFloatingIps(self.context) + floating_network = { + "id": "floating-net-id", + "name": "public", + "router:external": True + } + floatingip = {"id": "floating-ip-id"} + net = {"id": "net-id"} + subnet = {"id": "subnet-id"} + port = {"id": "port-id"} + router = {"id": "router-id"} - fip = {"floatingip": {"id": "floating-ip-id"}} - subnet = {"subnet": {}} - port = {"port": {"id": "port-id"}} - router = {"router": {}} + self.nc.create_floatingip.return_value = {"floatingip": floatingip} + self.nc.create_network.return_value = {"network": net} + self.nc.create_subnet.return_value = {"subnet": subnet} + self.nc.create_port.return_value = {"port": port} + self.nc.create_router.return_value = {"router": router} + self.nc.list_networks.return_value = {"networks": [floating_network]} - scenario._create_floatingip = mock.Mock(return_value=fip) - scenario._create_network = mock.Mock() - scenario._create_subnet = mock.Mock(return_value=subnet) - scenario._create_port = mock.Mock(return_value=port) - scenario._create_router = mock.Mock(return_value=router) - scenario._get_network_id = mock.Mock() - scenario._add_gateway_router = mock.Mock() - scenario._add_interface_router = mock.Mock() + network.AssociateAndDissociateFloatingIps(self.context).run( + floating_network=floating_network["name"]) - scenario._associate_floating_ip = mock.Mock() - scenario._dissociate_floating_ip = mock.Mock() + self.nc.create_floatingip.assert_called_once_with( + {"floatingip": {"description": mock.ANY, + "floating_network_id": floating_network["id"]}}) + self.nc.create_network.assert_called_once_with( + {"network": {"name": mock.ANY}} + ) + self.nc.create_subnet.assert_called_once_with( + {"subnet": { + "name": mock.ANY, + "network_id": net["id"], + "dns_nameservers": ["8.8.8.8", "8.8.4.4"], + "ip_version": 4, + "cidr": mock.ANY + }} + ) + self.nc.create_port.assert_called_once_with( + {"port": {"name": mock.ANY, + "network_id": net["id"]}} + ) + self.nc.add_gateway_router.assert_called_once_with( + router["id"], {"network_id": floating_network["id"]} + ) + self.nc.add_interface_router.assert_called_once_with( + router["id"], {"subnet_id": subnet["id"]} + ) - scenario.run(floating_network="public") + self.assertEqual( + [ + mock.call( + floatingip["id"], + {"floatingip": {"port_id": port["id"]}} + ), + mock.call( + floatingip["id"], + {"floatingip": {"port_id": None}} + ) + ], + self.nc.update_floatingip.call_args_list + ) - scenario._associate_floating_ip.assert_called_once_with( - floatingip=fip["floatingip"], port=port["port"]) - scenario._dissociate_floating_ip.assert_called_once_with( - floatingip=fip["floatingip"]) - - @mock.patch("%s.DeleteSubnets._delete_subnet" % BASE) - def test_delete_subnets(self, mock__delete_subnet): + def test_delete_subnets(self): # do not guess what user will be used self.context["user_choice_method"] = "round_robin" # if it is the 4th iteration, the second user from the second tenant @@ -659,7 +860,7 @@ class NeutronNetworksTestCase(test.ScenarioTestCase): self.assertEqual( [ - mock.call({"subnet": {"id": "subnet-3"}}), - mock.call({"subnet": {"id": "subnet-5"}}) + mock.call("subnet-3"), + mock.call("subnet-5") ], - mock__delete_subnet.call_args_list) + self.nc.delete_subnet.call_args_list) diff --git a/tests/unit/task/scenarios/neutron/test_utils.py b/tests/unit/task/scenarios/neutron/test_utils.py index 5bcec458..71f992f5 100644 --- a/tests/unit/task/scenarios/neutron/test_utils.py +++ b/tests/unit/task/scenarios/neutron/test_utils.py @@ -19,6 +19,7 @@ import ddt import netaddr from rally import exceptions +from rally_openstack.common import consts from rally_openstack.task.scenarios.neutron import utils from tests.unit import test @@ -251,6 +252,7 @@ class NeutronScenarioTestCase(test.ScenarioTestCase): "neutron.create_router") def test_create_router_with_ext_gw(self): + self._clients.credential.permission = consts.EndpointPermission.ADMIN net_id = "ext-net" self._nc.list_networks.return_value = { "networks": [{"id": net_id, "router:external": True}] diff --git a/tests/unit/task/scenarios/nova/test_servers.py b/tests/unit/task/scenarios/nova/test_servers.py index 667e8c2d..cd26b4e1 100644 --- a/tests/unit/task/scenarios/nova/test_servers.py +++ b/tests/unit/task/scenarios/nova/test_servers.py @@ -919,9 +919,15 @@ class NovaServersTestCase(test.ScenarioTestCase): scenario._get_console_url_server.assert_called_once_with( server, "novnc") - @mock.patch(NOVA_SERVERS_MODULE + ".network_wrapper.wrap") - def test_boot_and_associate_floating_ip(self, mock_wrap): - scenario = servers.BootAndAssociateFloatingIp(self.context) + def test_boot_and_associate_floating_ip(self): + clients = mock.MagicMock() + neutronclient = clients.neutron.return_value + floatingip = "floatingip" + neutronclient.create_floatingip.return_value = { + "floatingip": floatingip} + + scenario = servers.BootAndAssociateFloatingIp(self.context, + clients=clients) server = mock.Mock() scenario._boot_server = mock.Mock(return_value=server) scenario._associate_floating_ip = mock.Mock() @@ -932,16 +938,21 @@ class NovaServersTestCase(test.ScenarioTestCase): scenario._boot_server.assert_called_once_with(image, flavor, fakearg="fakearg") - net_wrap = mock_wrap.return_value - net_wrap.create_floating_ip.assert_called_once_with( - tenant_id=server.tenant_id) + neutronclient.create_floatingip.assert_called_once_with( + {"floatingip": mock.ANY} + ) scenario._associate_floating_ip.assert_called_once_with( - server, net_wrap.create_floating_ip.return_value["ip"]) + server, floatingip) + + def test_boot_server_associate_and_dissociate_floating_ip(self): + clients = mock.MagicMock() + neutronclient = clients.neutron.return_value + floatingip = "floatingip" + neutronclient.create_floatingip.return_value = { + "floatingip": floatingip} - @mock.patch(NOVA_SERVERS_MODULE + ".network_wrapper.wrap") - def test_boot_server_associate_and_dissociate_floating_ip(self, mock_wrap): scenario = servers.BootServerAssociateAndDissociateFloatingIP( - self.context) + self.context, clients=clients) server = mock.Mock() scenario._boot_server = mock.Mock(return_value=server) scenario._associate_floating_ip = mock.Mock() @@ -953,13 +964,13 @@ class NovaServersTestCase(test.ScenarioTestCase): scenario._boot_server.assert_called_once_with(image, flavor, fakearg="fakearg") - net_wrap = mock_wrap.return_value - net_wrap.create_floating_ip.assert_called_once_with( - tenant_id=server.tenant_id) + neutronclient.create_floatingip.assert_called_once_with( + {"floatingip": mock.ANY} + ) scenario._associate_floating_ip.assert_called_once_with( - server, net_wrap.create_floating_ip.return_value["ip"]) + server, floatingip) scenario._dissociate_floating_ip.assert_called_once_with( - server, net_wrap.create_floating_ip.return_value["ip"]) + server, floatingip) def test_boot_and_update_server(self): scenario = servers.BootAndUpdateServer(self.context) diff --git a/tests/unit/task/scenarios/vm/test_utils.py b/tests/unit/task/scenarios/vm/test_utils.py index 1eda763b..f4dabafb 100644 --- a/tests/unit/task/scenarios/vm/test_utils.py +++ b/tests/unit/task/scenarios/vm/test_utils.py @@ -136,7 +136,7 @@ class VMScenarioTestCase(test.ScenarioTestCase): addresses={"foo_net": [{"addr": "foo_ip"}]}, tenant_id="foo_tenant" ) - scenario = utils.VMScenario(self.context) + scenario = utils.VMScenario(self.context, clients=mock.MagicMock()) scenario._boot_server = mock.Mock(return_value=server) scenario._delete_server = mock.Mock() @@ -203,28 +203,29 @@ class VMScenarioTestCase(test.ScenarioTestCase): scenario._delete_floating_ip.assert_called_once_with(server, fip) scenario._delete_server.assert_called_once_with(server, force=True) - @mock.patch(VMTASKS_UTILS + ".network_wrapper.wrap") - def test__attach_floating_ip(self, mock_wrap): + def test__attach_floating_ip(self): scenario, server = self.get_scenario() + nc = scenario._clients.neutron.return_value - netwrap = mock_wrap.return_value - fip = {"id": "foo_id", "ip": "foo_ip"} - netwrap.create_floating_ip.return_value = fip + fip = {"id": "foo_id", "floating_ip_address": "foo_ip"} + nc.create_floatingip.return_value = {"floatingip": fip} + floating_network = {"id": "floating-network-id", + "name": "floating-network"} scenario._attach_floating_ip( - server, floating_network="bar_network") + server, floating_network=floating_network) - mock_wrap.assert_called_once_with(scenario.clients, scenario) - netwrap.create_floating_ip.assert_called_once_with( - ext_network="bar_network", - tenant_id="foo_tenant", fixed_ip="foo_ip") + nc.create_floatingip.assert_called_once_with({ + "floatingip": {"description": mock.ANY, + "floating_network_id": floating_network["id"]} + }) scenario._associate_floating_ip.assert_called_once_with( - server, fip, fixed_address="foo_ip") + server, fip, fixed_address=fip["floating_ip_address"]) - @mock.patch(VMTASKS_UTILS + ".network_wrapper.wrap") - def test__delete_floating_ip(self, mock_wrap): + def test__delete_floating_ip(self): scenario, server = self.get_scenario() + nc = scenario._clients.neutron.return_value _check_addr = mock.Mock(return_value=True) scenario.check_ip_address = mock.Mock(return_value=_check_addr) @@ -238,9 +239,7 @@ class VMScenarioTestCase(test.ScenarioTestCase): _check_addr.assert_called_once_with(server) scenario._dissociate_floating_ip.assert_called_once_with( server, fip) - mock_wrap.assert_called_once_with(scenario.clients, scenario) - mock_wrap.return_value.delete_floating_ip.assert_called_once_with( - "foo_id", wait=True) + nc.delete_floatingip.assert_called_once_with("foo_id") class HostTestCase(test.TestCase): diff --git a/tests/unit/verification/tempest/test_context.py b/tests/unit/verification/tempest/test_context.py index 1de4e0b7..88c9fa47 100644 --- a/tests/unit/verification/tempest/test_context.py +++ b/tests/unit/verification/tempest/test_context.py @@ -44,6 +44,7 @@ CRED = { "project_domain_name": "admin" } +NET_PATH = "rally_openstack.common.services.network" PATH = "rally_openstack.verification.tempest.context" @@ -266,17 +267,17 @@ class TempestContextTestCase(test.TestCase): client.create_subnet.side_effect = [{"subnet": {"id": "subid1"}}] client.list_networks.return_value = {"networks": []} - network = self.context._create_network_resources() - self.assertEqual("nid1", network["id"]) - self.assertEqual("nid1", self.context._created_networks[0]["id"]) - self.assertEqual("rid1", - self.context._created_networks[0]["router_id"]) - self.assertEqual("subid1", - self.context._created_networks[0]["subnets"][0]) + net_topo = self.context._create_network_resources() + + self.assertEqual("nid1", net_topo["network"]["id"]) + self.assertEqual("rid1", net_topo["routers"][0]["id"]) + self.assertEqual("subid1", net_topo["subnets"][0]["id"]) + + @mock.patch("%s.neutron.NeutronService.supports_extension" % PATH) + def test__create_network_resources_public_network_override( + self, mock_supports_extension): + mock_supports_extension.return_value = True - @mock.patch("rally_openstack.common.wrappers.network.NeutronWrapper.ext_gw_mode_enabled", # noqa E501 - new_callable=mock.PropertyMock, return_value=True) - def test__create_network_resources_public_network_override(self, mock_ext_gw_mode_enabled): # noqa E501 client = self.context.clients.neutron() conf = self.context.conf @@ -348,15 +349,16 @@ class TempestContextTestCase(test.TestCase): self.assertEqual("", self.context.conf.get("orchestration", "instance_type")) - @mock.patch("rally_openstack.common.wrappers." - "network.NeutronWrapper.delete_network") - def test__cleanup_network_resources( - self, mock_neutron_wrapper_delete_network): - self.context._created_networks = [{"name": "net-12345"}] + @mock.patch("%s.neutron.NeutronService.delete_network_topology" % PATH) + def test__cleanup_network_resources(self, mock_delete_network_topology): + self.context._created_networks = [{"network": {"name": "net-12345"}}] self.context.conf.set("compute", "fixed_network_name", "net-12345") self.context._cleanup_network_resources() - self.assertEqual(1, mock_neutron_wrapper_delete_network.call_count) + + mock_delete_network_topology.assert_called_once_with( + self.context._created_networks[0] + ) self.assertEqual("", self.context.conf.get("compute", "fixed_network_name"))