text: #    Copyright 2017 AT&T Corporation.
  #    All Rights Reserved.
  #
  #    Licensed under the Apache License, Version 2.0 (the "License"); you may
  #    not use this file except in compliance with the License. You may obtain
  #    a copy of the License at
  #
  #         http://www.apache.org/licenses/LICENSE-2.0
  #
  #    Unless required by applicable law or agreed to in writing, software
  #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  #    License for the specific language governing permissions and limitations
  #    under the License.
  
  import netaddr
  
  import testtools
  
  from tempest.common import utils
  from tempest.common import waiters
  from tempest import config
  from tempest.lib.common.utils import data_utils
  from tempest.lib.common.utils import test_utils
  from tempest.lib import decorators
  from tempest.lib import exceptions as lib_exc
  
  from patrole_tempest_plugin import rbac_exceptions
  from patrole_tempest_plugin import rbac_rule_validation
  from patrole_tempest_plugin.tests.api.compute import rbac_base
  
  CONF = config.CONF
  
  
  class MiscPolicyActionsRbacTest(rbac_base.BaseV2ComputeRbacTest):
      """Test multiple policy actions that require a server to be created.
  
      Minimize the number of servers that need to be created across classes
      by consolidating test cases related to different policy "families" into
      one class. This reduces the risk of running into `BuildErrorException`
      errors being raised due to too many servers being created simultaneously
      especially when higher concurrency is used.
  
      Only applies to:
        * policy "families" that require server creation
        * small policy "families" -- i.e. containing one to three policies
  
      Tests are ordered by policy name.
      """
  
      credentials = ['primary', 'admin']
  
      @classmethod
      def resource_setup(cls):
          super(MiscPolicyActionsRbacTest, cls).resource_setup()
          cls.server = cls.create_test_server(wait_until='ACTIVE')
  
      def setUp(self):
          super(MiscPolicyActionsRbacTest, self).setUp()
          try:
              waiters.wait_for_server_status(self.servers_client,
                                             self.server['id'], 'ACTIVE')
          except lib_exc.NotFound:
              # If the server was found to be deleted by a previous test,
              # a new one is built
              self.__class__.server = self.create_test_server(
                  wait_until='ACTIVE')
          except Exception:
              # Rebuilding the server in case something happened during a test
              self.__class__.server = self._rebuild_server(self.server['id'])
  
      def _rebuild_server(self, server_id):
          # Destroy an existing server and creates a new one.
          if server_id:
              self.delete_server(server_id)
  
          self.password = data_utils.rand_password()
          return self.create_test_server(
              wait_until='ACTIVE', adminPass=self.password)
  
      @utils.requires_ext(extension='os-admin-actions', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-admin-actions:reset_state")
      @decorators.idempotent_id('ae84dd0b-f364-462e-b565-3457f9c019ef')
      def test_reset_server_state(self):
          """Test reset server state, part of os-admin-actions."""
          with self.rbac_utils.override_role(self):
              self.servers_client.reset_state(self.server['id'], state='error')
          self.addCleanup(self.servers_client.reset_state, self.server['id'],
                          state='active')
  
      @utils.requires_ext(extension='os-admin-actions', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-admin-actions:inject_network_info")
      @decorators.idempotent_id('ce48c340-51c1-4cff-9b6e-0cc5ef008630')
      def test_inject_network_info(self):
          """Test inject network info, part of os-admin-actions."""
          with self.rbac_utils.override_role(self):
              self.servers_client.inject_network_info(self.server['id'])
  
      @utils.requires_ext(extension='os-admin-actions', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-admin-actions:reset_network")
      @decorators.idempotent_id('2911a242-15c4-4fcb-80d5-80a8930661b0')
      def test_reset_network(self):
          """Test reset network, part of os-admin-actions."""
          with self.rbac_utils.override_role(self):
              self.servers_client.reset_network(self.server['id'])
  
      @testtools.skipUnless(CONF.compute_feature_enabled.change_password,
                            'Change password not available.')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-admin-password")
      @decorators.idempotent_id('908a7d59-3a66-441c-94cf-38e57ed14956')
      def test_change_server_password(self):
          """Test change admin password, part of os-admin-password."""
          original_password = self.servers_client.show_password(
              self.server['id'])
  
          with self.rbac_utils.override_role(self):
              self.servers_client.change_password(
                  self.server['id'], adminPass=data_utils.rand_password())
          self.addCleanup(self.servers_client.change_password, self.server['id'],
                          adminPass=original_password)
          waiters.wait_for_server_status(
              self.servers_client, self.server['id'], 'ACTIVE')
  
      @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein,
                        "This API extension policy was removed in Stein")
      @utils.requires_ext(extension='os-config-drive', service='compute')
      @decorators.idempotent_id('2c82e819-382d-4d6f-87f0-a45954cbbc64')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-config-drive")
      def test_list_servers_with_details_config_drive(self):
          """Test list servers with config_drive property in response body."""
          with self.rbac_utils.override_role(self):
              body = self.servers_client.list_servers(detail=True)['servers']
          expected_attr = 'config_drive'
          # If the first server contains "config_drive", then all the others do.
          if expected_attr not in body[0]:
              raise rbac_exceptions.RbacMalformedResponse(
                  attribute=expected_attr)
  
      @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein,
                        "This API extension policy was removed in Stein")
      @utils.requires_ext(extension='os-config-drive', service='compute')
      @decorators.idempotent_id('55c62ef7-b72b-4970-acc6-05b0a4316e5d')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-config-drive")
      def test_show_server_config_drive(self):
          """Test show server with config_drive property in response body."""
          with self.rbac_utils.override_role(self):
              body = self.servers_client.show_server(self.server['id'])['server']
          expected_attr = 'config_drive'
          if expected_attr not in body:
              raise rbac_exceptions.RbacMalformedResponse(
                  attribute=expected_attr)
  
      @utils.requires_ext(extension='os-deferred-delete', service='compute')
      @decorators.idempotent_id('189bfed4-1e6d-475c-bb8c-d57e60895391')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-deferred-delete")
      def test_force_delete_server(self):
          """Test force delete server, part of os-deferred-delete."""
          with self.rbac_utils.override_role(self):
              # Force-deleting a server enforces os-deferred-delete.
              self.servers_client.force_delete_server(self.server['id'])
  
      @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein,
                        "This API extension policy was removed in Stein")
      @decorators.idempotent_id('d873740a-7b10-40a9-943d-7cc18115370e')
      @utils.requires_ext(extension='OS-EXT-AZ', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-extended-availability-zone")
      def test_list_servers_with_details_extended_availability_zone(self):
          """Test list servers OS-EXT-AZ:availability_zone attr in resp body."""
          expected_attr = 'OS-EXT-AZ:availability_zone'
  
          with self.rbac_utils.override_role(self):
              body = self.servers_client.list_servers(detail=True)['servers']
          # If the first server contains `expected_attr`, then all the others do.
          if expected_attr not in body[0]:
              raise rbac_exceptions.RbacMalformedResponse(
                  attribute=expected_attr)
  
      @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein,
                        "This API extension policy was removed in Stein")
      @decorators.idempotent_id('727e5360-770a-4b9c-8015-513a40216635')
      @utils.requires_ext(extension='OS-EXT-AZ', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-extended-availability-zone")
      def test_show_server_extended_availability_zone(self):
          """Test show server OS-EXT-AZ:availability_zone attr in resp body."""
          expected_attr = 'OS-EXT-AZ:availability_zone'
  
          with self.rbac_utils.override_role(self):
              body = self.servers_client.show_server(self.server['id'])['server']
          if expected_attr not in body:
              raise rbac_exceptions.RbacMalformedResponse(
                  attribute=expected_attr)
  
      @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein,
                        "This API extension policy was removed in Stein")
      @decorators.idempotent_id('4aa5d93e-4887-468a-8eb4-b6eca0ca6437')
      @utils.requires_ext(extension='OS-EXT-SRV-ATTR', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-extended-server-attributes")
      def test_list_servers_extended_server_attributes(self):
          """Test list servers with details, with extended server attributes in
          response body.
          """
          with self.rbac_utils.override_role(self):
              body = self.servers_client.list_servers(detail=True)['servers']
  
          # NOTE(felipemonteiro): The attributes included below should be
          # returned by all microversions. We don't include tests for other
          # microversions since Tempest schema validation takes care of that in
          # `show_server` call above. (Attributes there are *optional*.)
          for attr in ('host', 'instance_name'):
              whole_attr = 'OS-EXT-SRV-ATTR:%s' % attr
              if whole_attr not in body[0]:
                  raise rbac_exceptions.RbacMalformedResponse(
                      attribute=whole_attr)
  
      @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein,
                        "This API extension policy was removed in Stein")
      @decorators.idempotent_id('2ed7aee2-94b2-4a9f-ae63-a51b7f94fe30')
      @utils.requires_ext(extension='OS-EXT-SRV-ATTR', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-extended-server-attributes")
      def test_show_server_extended_server_attributes(self):
          """Test show server with extended server attributes in response
          body.
          """
          with self.rbac_utils.override_role(self):
              body = self.servers_client.show_server(self.server['id'])['server']
  
          # NOTE(felipemonteiro): The attributes included below should be
          # returned by all microversions. We don't include tests for other
          # microversions since Tempest schema validation takes care of that in
          # `show_server` call above. (Attributes there are *optional*.)
          for attr in ('host', 'instance_name'):
              whole_attr = 'OS-EXT-SRV-ATTR:%s' % attr
              if whole_attr not in body:
                  raise rbac_exceptions.RbacMalformedResponse(
                      attribute=whole_attr)
  
      @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein,
                        "This API extension policy was removed in Stein")
      @decorators.idempotent_id('82053c27-3134-4003-9b55-bc9fafdb0e3b')
      @utils.requires_ext(extension='OS-EXT-STS', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-extended-status")
      def test_list_servers_extended_status(self):
          """Test list servers with extended properties in response body."""
          with self.rbac_utils.override_role(self):
              body = self.servers_client.list_servers(detail=True)['servers']
  
          expected_attrs = ('OS-EXT-STS:task_state', 'OS-EXT-STS:vm_state',
                            'OS-EXT-STS:power_state')
          for attr in expected_attrs:
              if attr not in body[0]:
                  raise rbac_exceptions.RbacMalformedResponse(
                      attribute=attr)
  
      @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein,
                        "This API extension policy was removed in Stein")
      @decorators.idempotent_id('7d2620a5-eea1-4a8b-96ea-86ad77a73fc8')
      @utils.requires_ext(extension='OS-EXT-STS', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-extended-status")
      def test_show_server_extended_status(self):
          """Test show server with extended properties in response body."""
          with self.rbac_utils.override_role(self):
              body = self.servers_client.show_server(self.server['id'])['server']
  
          expected_attrs = ('OS-EXT-STS:task_state', 'OS-EXT-STS:vm_state',
                            'OS-EXT-STS:power_state')
          for attr in expected_attrs:
              if attr not in body:
                  raise rbac_exceptions.RbacMalformedResponse(
                      attribute=attr)
  
      @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein,
                        "This API extension policy was removed in Stein")
      @decorators.idempotent_id('21e39cbe-6c32-48fc-80dd-3e1fece6053f')
      @utils.requires_ext(extension='os-extended-volumes', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-extended-volumes")
      def test_list_servers_with_details_extended_volumes(self):
          """Test list servers os-extended-volumes:volumes_attached attr in resp
          body.
          """
          expected_attr = 'os-extended-volumes:volumes_attached'
  
          with self.rbac_utils.override_role(self):
              body = self.servers_client.list_servers(detail=True)['servers']
          if expected_attr not in body[0]:
              raise rbac_exceptions.RbacMalformedResponse(
                  attribute=expected_attr)
  
      @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein,
                        "This API extension policy was removed in Stein")
      @decorators.idempotent_id('7f163708-0d25-4138-8512-dfdd72a92989')
      @utils.requires_ext(extension='os-extended-volumes', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-extended-volumes")
      def test_show_server_extended_volumes(self):
          """Test show server os-extended-volumes:volumes_attached attr in resp
          body.
          """
          expected_attr = 'os-extended-volumes:volumes_attached'
  
          with self.rbac_utils.override_role(self):
              body = self.servers_client.show_server(self.server['id'])['server']
          if expected_attr not in body:
              raise rbac_exceptions.RbacMalformedResponse(
                  attribute=expected_attr)
  
      @utils.requires_ext(extension='os-instance-actions', service='compute')
      @decorators.idempotent_id('9d1b131d-407e-4fa3-8eef-eb2c4526f1da')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-instance-actions")
      def test_list_instance_actions(self):
          """Test list instance actions, part of os-instance-actions."""
          with self.rbac_utils.override_role(self):
              self.servers_client.list_instance_actions(self.server['id'])
  
      @utils.requires_ext(extension='os-instance-actions', service='compute')
      @decorators.idempotent_id('eb04c439-4215-4029-9ccb-5b3c041bfc25')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-instance-actions:events")
      def test_show_instance_action(self):
          """Test show instance action, part of os-instance-actions.
  
          Expect "events" details to be included in the response body.
          """
          # NOTE: "os_compute_api:os-instance-actions" is also enforced.
          request_id = self.server.response['x-compute-request-id']
  
          with self.rbac_utils.override_role(self):
              instance_action = self.servers_client.show_instance_action(
                  self.server['id'], request_id)['instanceAction']
  
          if 'events' not in instance_action:
              raise rbac_exceptions.RbacMalformedResponse(
                  attribute='events')
          # Microversion 2.51+ returns 'events' always, but not 'traceback'. If
          # 'traceback' is also present then policy enforcement passed.
          if 'traceback' not in instance_action['events'][0]:
              raise rbac_exceptions.RbacMalformedResponse(
                  attribute='events.traceback')
  
      @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein,
                        "This API extension policy was removed in Stein")
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-keypairs")
      @decorators.idempotent_id('81e6fa34-c06b-42ca-b195-82bf8699b940')
      def test_show_server_keypair(self):
          with self.rbac_utils.override_role(self):
              result = self.servers_client.show_server(self.server['id'])[
                  'server']
          if 'key_name' not in result:
              raise rbac_exceptions.RbacMalformedResponse(
                  attribute='key_name')
  
      @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein,
                        "This API extension policy was removed in Stein")
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-keypairs")
      @decorators.idempotent_id('41ca4280-ec59-4b80-a9b1-6bc6366faf39')
      def test_list_servers_keypairs(self):
          with self.rbac_utils.override_role(self):
              result = self.servers_client.list_servers(detail=True)['servers']
          if 'key_name' not in result[0]:
              raise rbac_exceptions.RbacMalformedResponse(
                  attribute='key_name')
  
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-lock-server:lock")
      @decorators.idempotent_id('b81e10fb-1864-498f-8c1d-5175c6fec5fb')
      def test_lock_server(self):
          """Test lock server, part of os-lock-server."""
          with self.rbac_utils.override_role(self):
              self.servers_client.lock_server(self.server['id'])
          self.addCleanup(self.servers_client.unlock_server, self.server['id'])
  
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-lock-server:unlock")
      @decorators.idempotent_id('d50ef8e8-4bce-11e7-b114-b2f933d5fe66')
      def test_unlock_server(self):
          """Test unlock server, part of os-lock-server."""
          self.servers_client.lock_server(self.server['id'])
          self.addCleanup(self.servers_client.unlock_server, self.server['id'])
  
          with self.rbac_utils.override_role(self):
              self.servers_client.unlock_server(self.server['id'])
  
      @rbac_rule_validation.action(
          service="nova",
          rules=["os_compute_api:os-lock-server:unlock",
                 "os_compute_api:os-lock-server:unlock:unlock_override"])
      @decorators.idempotent_id('40dfeef9-73ee-48a9-be19-a219875de457')
      def test_unlock_server_override(self):
          """Test force unlock server, part of os-lock-server.
  
          In order to trigger the unlock:unlock_override policy instead
          of the unlock policy, the server must be locked by a different
          user than the one who is attempting to unlock it.
          """
          self.os_admin.servers_client.lock_server(self.server['id'])
          self.addCleanup(self.servers_client.unlock_server, self.server['id'])
  
          with self.rbac_utils.override_role(self):
              self.servers_client.unlock_server(self.server['id'])
  
      @utils.requires_ext(extension='os-rescue', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-rescue")
      @decorators.idempotent_id('fbbb2afc-ed0e-4552-887d-ac00fb5d436e')
      def test_rescue_server(self):
          """Test rescue server, part of os-rescue."""
          with self.rbac_utils.override_role(self):
              self.servers_client.rescue_server(self.server['id'])
          waiters.wait_for_server_status(
              self.servers_client, self.server['id'], 'RESCUE')
  
      @decorators.idempotent_id('ac2d956f-d6a3-4184-b814-b44d05c9574c')
      @utils.requires_ext(extension='os-rescue', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-rescue")
      def test_unrescue_server(self):
          """Test unrescue server, part of os-rescue."""
          self.servers_client.rescue_server(self.server['id'])
          waiters.wait_for_server_status(
              self.servers_client, self.server['id'], 'RESCUE')
  
          with self.rbac_utils.override_role(self):
              self.servers_client.unrescue_server(self.server['id'])
          waiters.wait_for_server_status(
              self.servers_client, self.server['id'], 'ACTIVE')
  
      @utils.requires_ext(extension='os-server-diagnostics', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-server-diagnostics")
      @decorators.idempotent_id('5dabfcc4-bedb-417b-8247-b3ee7c5c0f3e')
      def test_show_server_diagnostics(self):
          """Test show server diagnostics, part of os-server-diagnostics."""
          with self.rbac_utils.override_role(self):
              self.servers_client.show_server_diagnostics(self.server['id'])
  
      @utils.requires_ext(extension='os-server-password', service='compute')
      @decorators.idempotent_id('aaf43f78-c178-4581-ac18-14afd3f1f6ba')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-server-password")
      def test_delete_server_password(self):
          """Test delete server password, part of os-server-password."""
          with self.rbac_utils.override_role(self):
              self.servers_client.delete_password(self.server['id'])
  
      @utils.requires_ext(extension='os-server-password', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-server-password")
      @decorators.idempotent_id('f677971a-7d20-493c-977f-6ff0a74b5b2c')
      def test_get_server_password(self):
          """Test show server password, part of os-server-password."""
          with self.rbac_utils.override_role(self):
              self.servers_client.show_password(self.server['id'])
  
      @testtools.skipIf(CONF.policy_feature_enabled.removed_nova_policies_stein,
                        "This API extension policy was removed in Stein")
      @utils.requires_ext(extension='OS-SRV-USG', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-server-usage")
      @decorators.idempotent_id('f0437ead-b9fb-462a-9f3d-ce53fac9d57a')
      def test_show_server_usage(self):
          """Test show server usage, part of os-server-usage.
  
          TODO(felipemonteiro): Once multiple policy testing is supported, this
          test should also check for additional policies mentioned here:
          https://github.com/openstack/nova/blob/master/nova/policies/server_usage.py
          """
          expected_attrs = ('OS-SRV-USG:launched_at',
                            'OS-SRV-USG:terminated_at')
  
          with self.rbac_utils.override_role(self):
              body = self.servers_client.show_server(self.server['id'])['server']
          for expected_attr in expected_attrs:
              if expected_attr not in body:
                  raise rbac_exceptions.RbacMalformedResponse(
                      attribute=expected_attr)
  
      @utils.requires_ext(extension='os-simple-tenant-usage', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-simple-tenant-usage:list")
      @decorators.idempotent_id('2aef094f-0452-4df6-a66a-0ec22a92b16e')
      def test_list_simple_tenant_usages(self):
          """Test list tenant usages, part of os-simple-tenant-usage."""
          with self.rbac_utils.override_role(self):
              self.tenant_usages_client.list_tenant_usages()
  
      @utils.requires_ext(extension='os-simple-tenant-usage', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-simple-tenant-usage:show")
      @decorators.idempotent_id('fe7eacda-15c4-4bf7-93ef-1091c4546a9d')
      def test_show_simple_tenant_usage(self):
          """Test show tenant usage, part of os-simple-tenant-usage."""
          tenant_id = self.os_primary.credentials.tenant_id
  
          with self.rbac_utils.override_role(self):
              self.tenant_usages_client.show_tenant_usage(tenant_id=tenant_id)
  
      @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                            "Suspend compute feature is not available.")
      @decorators.idempotent_id('b775930f-237c-431c-83ae-d33ed1b9700b')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-suspend-server:suspend")
      def test_suspend_server(self):
          """Test suspend server, part of os-suspend-server."""
          with self.rbac_utils.override_role(self):
              self.servers_client.suspend_server(self.server['id'])
          self.addCleanup(self.servers_client.resume_server, self.server['id'])
          waiters.wait_for_server_status(
              self.servers_client, self.server['id'], 'SUSPENDED')
  
      @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                            "Suspend compute feature is not available.")
      @decorators.idempotent_id('4d90bd02-11f8-45b1-a8a1-534665584675')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-suspend-server:resume")
      def test_resume_server(self):
          """Test resume server, part of os-suspend-server."""
          self.servers_client.suspend_server(self.server['id'])
          waiters.wait_for_server_status(
              self.servers_client, self.server['id'], 'SUSPENDED')
  
          with self.rbac_utils.override_role(self):
              self.servers_client.resume_server(self.server['id'])
          waiters.wait_for_server_status(
              self.servers_client, self.server['id'], 'ACTIVE')
  
  
  class MiscPolicyActionsNetworkRbacTest(rbac_base.BaseV2ComputeRbacTest):
      """Test multiple policy actions that require a server to be created.
  
      Only applies to:
        * policy "families" that require server creation
        * small policy "families" -- i.e. containing one to three policies
        * tests that require network resources
      """
  
      @classmethod
      def skip_checks(cls):
          super(MiscPolicyActionsNetworkRbacTest, cls).skip_checks()
          # All tests below require Neutron availability.
          if not CONF.service_available.neutron:
              raise cls.skipException(
                  '%s skipped as Neutron is required' % cls.__name__)
  
      @classmethod
      def setup_credentials(cls):
          cls.prepare_instance_network()
          super(MiscPolicyActionsNetworkRbacTest, cls).setup_credentials()
  
      @classmethod
      def resource_setup(cls):
          def _cleanup_ports(network_id):
              ports = cls.ports_client.list_ports(network_id=network_id)['ports']
              for port in ports:
                  test_utils.call_and_ignore_notfound_exc(
                      cls.ports_client.delete_port,
                      port['id'])
  
          super(MiscPolicyActionsNetworkRbacTest, cls).resource_setup()
          cls.server = cls.create_test_server(wait_until='ACTIVE')
  
          # Create network the interface will be attached to
          network_name = \
              data_utils.rand_name(cls.__class__.__name__ + '-network')
          post_body = {'name': network_name}
          post_body['router:external'] = False
          post_body['shared'] = True
          post_body['port_security_enabled'] = True
          cls.network = \
              cls.networks_client.create_network(**post_body)['network']
          cls.addClassResourceCleanup(
              cls.networks_client.delete_network,
              cls.network['id'])
  
          # Create subnet for network
          cls.cidr = netaddr.IPNetwork(CONF.network.project_network_cidr)
          cls.subnet = cls.subnets_client.create_subnet(
              network_id=cls.network['id'],
              cidr=cls.cidr,
              ip_version=4)['subnet']
          cls.addClassResourceCleanup(
              cls.subnets_client.delete_subnet,
              cls.subnet['id'])
  
          # ports on the network need to be deleted before the network can
          # be deleted
          cls.addClassResourceCleanup(_cleanup_ports, cls.network['id'])
  
      def _attach_interface_to_server(self):
          network_id = self.network['id']
          interface = self.interfaces_client.create_interface(
              self.server['id'], net_id=network_id)['interfaceAttachment']
          self.addCleanup(
              waiters.wait_for_interface_detach, self.interfaces_client,
              self.server['id'], interface['port_id'])
          self.addCleanup(
              test_utils.call_and_ignore_notfound_exc,
              self.interfaces_client.delete_interface,
              self.server['id'], interface['port_id'])
          waiters.wait_for_interface_status(
              self.interfaces_client, self.server['id'],
              interface['port_id'], 'ACTIVE')
          return interface
  
      @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
                            "Interface attachment is not available.")
      @utils.requires_ext(extension='os-attach-interfaces', service='compute')
      @decorators.idempotent_id('ddf53cb6-4a0a-4e5a-91e3-6c32aaa3b9b6')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-attach-interfaces")
      def test_list_interfaces(self):
          """Test list interfaces, part of os-attach-interfaces."""
          with self.rbac_utils.override_role(self):
              self.interfaces_client.list_interfaces(self.server['id'])
  
      @decorators.idempotent_id('1b9cf7db-dc50-48a2-8eb9-8c25af5e934a')
      @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
                            "Interface attachment is not available.")
      @utils.requires_ext(extension='os-attach-interfaces', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-attach-interfaces")
      def test_show_interface(self):
          """Test show interfaces, part of os-attach-interfaces."""
          interface = self._attach_interface_to_server()
          with self.rbac_utils.override_role(self):
              self.interfaces_client.show_interface(
                  self.server['id'], interface['port_id'])
  
      @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
                            "Interface attachment is not available.")
      @utils.requires_ext(extension='os-attach-interfaces', service='compute')
      @decorators.idempotent_id('d2d3a24d-4738-4bce-a287-36d664746cde')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-attach-interfaces:create")
      def test_create_interface(self):
          """Test create interface, part of os-attach-interfaces."""
          network_id = self.network['id']
          with self.rbac_utils.override_role(self):
              interface = self.interfaces_client.create_interface(
                  self.server['id'], net_id=network_id)['interfaceAttachment']
          self.addCleanup(
              waiters.wait_for_interface_detach, self.interfaces_client,
              self.server['id'], interface['port_id'])
          self.addCleanup(
              test_utils.call_and_ignore_notfound_exc,
              self.interfaces_client.delete_interface,
              self.server['id'], interface['port_id'])
          waiters.wait_for_interface_status(
              self.interfaces_client, self.server['id'],
              interface['port_id'], 'ACTIVE')
  
      @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
                            "Interface attachment is not available.")
      @utils.requires_ext(extension='os-attach-interfaces', service='compute')
      @decorators.idempotent_id('55b05692-ed44-4608-a84c-cd4219c82799')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:os-attach-interfaces:delete")
      def test_delete_interface(self):
          """Test delete interface, part of os-attach-interfaces."""
          interface = self._attach_interface_to_server()
  
          with self.rbac_utils.override_role(self):
              self.interfaces_client.delete_interface(self.server['id'],
                                                      interface['port_id'])
          waiters.wait_for_interface_detach(
              self.interfaces_client, self.server['id'], interface['port_id'])
  
      @decorators.idempotent_id('6886d360-0d86-4760-b1a3-882d81fbebcc')
      @utils.requires_ext(extension='os-ips', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:ips:index")
      def test_list_addresses(self):
          """Test list server addresses, part of ips policy family."""
          with self.rbac_utils.override_role(self):
              self.servers_client.list_addresses(self.server['id'])
  
      @decorators.idempotent_id('fa43e7e5-0db9-48eb-9c6b-c11eb766b8e4')
      @utils.requires_ext(extension='os-ips', service='compute')
      @rbac_rule_validation.action(
          service="nova",
          rule="os_compute_api:ips:show")
      def test_list_addresses_by_network(self):
          """Test list server addresses by network, part of ips policy family."""
          addresses = self.servers_client.list_addresses(self.server['id'])[
              'addresses']
          address = next(iter(addresses))
  
          with self.rbac_utils.override_role(self):
              self.servers_client.list_addresses_by_network(
                  self.server['id'], address)
  
      @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
                            "Interface attachment is not available.")
      @utils.requires_ext(extension='os-multinic', service='compute')
      @rbac_rule_validation.action(
          service="nova", rule="os_compute_api:os-multinic")
      @decorators.idempotent_id('bd3e2c74-130a-40f0-8085-124d93fe67da')
      def test_add_fixed_ip(self):
          """Test add fixed ip to server network, part of os-multinic."""
          interfaces = (self.interfaces_client.list_interfaces(self.server['id'])
                        ['interfaceAttachments'])
          if interfaces:
              network_id = interfaces[0]['net_id']
          else:
              interface = self.interfaces_client.create_interface(
                  self.server['id'])['interfaceAttachment']
              network_id = interface['net_id']
              self.addCleanup(
                  waiters.wait_for_interface_detach, self.interfaces_client,
                  self.server['id'], interface['port_id'])
              self.addCleanup(
                  self.interfaces_client.delete_interface,
                  self.server['id'], interface['port_id'])
  
          with self.rbac_utils.override_role(self):
              self.servers_client.add_fixed_ip(self.server['id'],
                                               networkId=network_id)
          # Get the Fixed IP from server.
          server_detail = self.servers_client.show_server(
              self.server['id'])['server']
          fixed_ip = None
          for ip_set in server_detail['addresses']:
              for ip in server_detail['addresses'][ip_set]:
                  if ip['OS-EXT-IPS:type'] == 'fixed':
                      fixed_ip = ip['addr']
                      break
              if fixed_ip is not None:
                  break
          # Remove the fixed IP from server.
          self.servers_client.remove_fixed_ip(self.server['id'],
                                              address=fixed_ip)
  