Merge "Skip boto tests when auth_version is v3"
diff --git a/tempest/api/identity/admin/v3/test_default_project_id.py b/tempest/api/identity/admin/v3/test_default_project_id.py
index 5555ee8..9841cc8 100644
--- a/tempest/api/identity/admin/v3/test_default_project_id.py
+++ b/tempest/api/identity/admin/v3/test_default_project_id.py
@@ -76,7 +76,7 @@
# create a new client with user's credentials (NOTE: unscoped token!)
creds = auth.KeystoneV3Credentials(username=user_name,
password=user_name,
- domain_name=dom_name)
+ user_domain_name=dom_name)
auth_provider = manager.get_auth_provider(creds)
creds = auth_provider.fill_credentials()
admin_client = clients.Manager(credentials=creds)
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index 0611393..b5b1d7b 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -144,11 +144,11 @@
self.client.add_group_user(self.group_body['id'], self.user_body['id'])
self.addCleanup(self.client.delete_group_user,
self.group_body['id'], self.user_body['id'])
- body = self.token.auth(user=self.user_body['id'],
+ body = self.token.auth(user_id=self.user_body['id'],
password=self.u_password,
- user_domain=self.domain['name'],
- project=self.project['name'],
- project_domain=self.domain['name'])
+ user_domain_name=self.domain['name'],
+ project_name=self.project['name'],
+ project_domain_name=self.domain['name'])
roles = body['token']['roles']
self.assertEqual(len(roles), 1)
self.assertEqual(roles[0]['id'], self.role['id'])
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index 5cc498f..7358ce9 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -36,7 +36,8 @@
email=u_email)
self.addCleanup(self.client.delete_user, user['id'])
# Perform Authentication
- resp = self.token.auth(user['id'], u_password).response
+ resp = self.token.auth(user_id=user['id'],
+ password=u_password).response
subject_token = resp['x-subject-token']
# Perform GET Token
token_details = self.client.get_token(subject_token)
@@ -87,7 +88,7 @@
role['id'])
# Get an unscoped token.
- token_auth = self.token.auth(user=user['id'],
+ token_auth = self.token.auth(user_id=user['id'],
password=user_password)
token_id = token_auth.response['x-subject-token']
@@ -110,8 +111,8 @@
# Use the unscoped token to get a scoped token.
token_auth = self.token.auth(token=token_id,
- project=project1_name,
- project_domain='Default')
+ project_name=project1_name,
+ project_domain_name='Default')
token1_id = token_auth.response['x-subject-token']
self.assertEqual(orig_expires_at, token_auth['token']['expires_at'],
@@ -140,8 +141,8 @@
# Now get another scoped token using the unscoped token.
token_auth = self.token.auth(token=token_id,
- project=project2_name,
- project_domain='Default')
+ project_name=project2_name,
+ project_domain_name='Default')
self.assertEqual(project2['id'],
token_auth['token']['project']['id'])
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index f29e72a..9d9f61c 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -79,7 +79,8 @@
new_password = data_utils.rand_name('pass1')
self.client.update_user_password(user['id'], new_password,
original_password)
- resp = self.token.auth(user['id'], new_password).response
+ resp = self.token.auth(user_id=user['id'],
+ password=new_password).response
subject_token = resp['x-subject-token']
# Perform GET Token to verify and confirm password is updated
token_details = self.client.get_token(subject_token)
diff --git a/tempest/auth.py b/tempest/auth.py
index 3247cb5..113ad69 100644
--- a/tempest/auth.py
+++ b/tempest/auth.py
@@ -328,11 +328,17 @@
def _auth_params(self):
return dict(
- user=self.credentials.username,
+ user_id=self.credentials.user_id,
+ username=self.credentials.username,
password=self.credentials.password,
- project=self.credentials.tenant_name,
- user_domain=self.credentials.user_domain_name,
- project_domain=self.credentials.project_domain_name,
+ project_id=self.credentials.project_id,
+ project_name=self.credentials.project_name,
+ user_domain_id=self.credentials.user_domain_id,
+ user_domain_name=self.credentials.user_domain_name,
+ project_domain_id=self.credentials.project_domain_id,
+ project_domain_name=self.credentials.project_domain_name,
+ domain_id=self.credentials.domain_id,
+ domain_name=self.credentials.domain_name,
auth_data=True)
def _fill_credentials(self, auth_data_body):
@@ -579,7 +585,7 @@
Credentials suitable for the Keystone Identity V3 API
"""
- ATTRIBUTES = ['domain_name', 'password', 'tenant_name', 'username',
+ ATTRIBUTES = ['domain_id', 'domain_name', 'password', 'username',
'project_domain_id', 'project_domain_name', 'project_id',
'project_name', 'tenant_id', 'tenant_name', 'user_domain_id',
'user_domain_name', 'user_id']
@@ -625,6 +631,8 @@
- None
- Project id (optional domain)
- Project name and its domain id/name
+ - Domain id
+ - Domain name
"""
valid_user_domain = any(
[self.user_domain_id is not None,
@@ -635,11 +643,16 @@
valid_user = any(
[self.user_id is not None,
self.username is not None and valid_user_domain])
- valid_project = any(
+ valid_project_scope = any(
[self.project_name is None and self.project_id is None,
self.project_id is not None,
self.project_name is not None and valid_project_domain])
- return all([self.password is not None, valid_user, valid_project])
+ valid_domain_scope = any(
+ [self.domain_id is None and self.domain_name is None,
+ self.domain_id or self.domain_name])
+ return all([self.password is not None,
+ valid_user,
+ valid_project_scope and valid_domain_scope])
IDENTITY_VERSION = {'v2': (KeystoneV2Credentials, KeystoneV2AuthProvider),
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 7a60403..a5d4d34 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -101,13 +101,19 @@
self.servers = []
def _setup_network_and_servers(self, **kwargs):
+ boot_with_port = kwargs.pop('boot_with_port', False)
self.security_group = \
self._create_security_group(tenant_id=self.tenant_id)
self.network, self.subnet, self.router = self.create_networks(**kwargs)
self.check_networks()
+ self.port_id = None
+ if boot_with_port:
+ # create a port on the network and boot with that
+ self.port_id = self._create_port(self.network['id']).id
+
name = data_utils.rand_name('server-smoke')
- server = self._create_server(name, self.network)
+ server = self._create_server(name, self.network, self.port_id)
self._check_tenant_network_connectivity()
floating_ip = self.create_floating_ip(server)
@@ -141,7 +147,7 @@
self.assertIn(self.router.id,
seen_router_ids)
- def _create_server(self, name, network):
+ def _create_server(self, name, network, port_id=None):
keypair = self.create_keypair()
self.keypairs[keypair['name']] = keypair
security_groups = [{'name': self.security_group['name']}]
@@ -152,6 +158,8 @@
'key_name': keypair['name'],
'security_groups': security_groups,
}
+ if port_id is not None:
+ create_kwargs['networks'][0]['port'] = port_id
server = self.create_server(name=name, create_kwargs=create_kwargs)
self.servers.append(server)
return server
@@ -603,3 +611,36 @@
self.check_public_network_connectivity(
should_connect=True, msg="after updating "
"admin_state_up of instance port to True")
+
+ @test.idempotent_id('759462e1-8535-46b0-ab3a-33aa45c55aaa')
+ @test.attr(type='smoke')
+ @test.services('compute', 'network')
+ def test_preserve_preexisting_port(self):
+ """Tests that a pre-existing port provided on server boot is not
+ deleted if the server is deleted.
+
+ Nova should unbind the port from the instance on delete if the port was
+ not created by Nova as part of the boot request.
+ """
+ # Setup the network, create a port and boot the server from that port.
+ self._setup_network_and_servers(boot_with_port=True)
+ _, server = self.floating_ip_tuple
+ self.assertIsNotNone(self.port_id,
+ 'Server should have been created from a '
+ 'pre-existing port.')
+ # Assert the port is bound to the server.
+ port_list = self._list_ports(device_id=server['id'],
+ network_id=self.network['id'])
+ self.assertEqual(1, len(port_list),
+ 'There should only be one port created for '
+ 'server %s.' % server['id'])
+ self.assertEqual(self.port_id, port_list[0]['id'])
+ # Delete the server.
+ self.servers_client.delete_server(server['id'])
+ self.servers_client.wait_for_server_termination(server['id'])
+ # Assert the port still exists on the network but is unbound from
+ # the deleted server.
+ port = self.network_client.show_port(self.port_id)['port']
+ self.assertEqual(self.network['id'], port['network_id'])
+ self.assertEqual('', port['device_id'])
+ self.assertEqual('', port['device_owner'])
diff --git a/tempest/services/identity/v3/json/token_client.py b/tempest/services/identity/v3/json/token_client.py
index b0824a7..3e37403 100644
--- a/tempest/services/identity/v3/json/token_client.py
+++ b/tempest/services/identity/v3/json/token_client.py
@@ -37,22 +37,30 @@
self.auth_url = auth_url
- def auth(self, user=None, password=None, project=None, user_type='id',
- user_domain=None, project_domain=None, token=None):
+ def auth(self, user_id=None, username=None, password=None, project_id=None,
+ project_name=None, user_domain_id=None, user_domain_name=None,
+ project_domain_id=None, project_domain_name=None, domain_id=None,
+ domain_name=None, token=None):
"""
- :param user: user id or name, as specified in user_type
- :param user_domain: the user domain
- :param project_domain: the project domain
+ :param user_id: user id
+ :param username: user name
+ :param user_domain_id: the user domain id
+ :param user_domain_name: the user domain name
+ :param project_domain_id: the project domain id
+ :param project_domain_name: the project domain name
+ :param domain_id: a domain id to scope to
+ :param domain_name: a domain name to scope to
+ :param project_id: a project id to scope to
+ :param project_name: a project name to scope to
:param token: a token to re-scope.
- Accepts different combinations of credentials. Restrictions:
- - project and domain are only name (no id)
+ Accepts different combinations of credentials.
Sample sample valid combinations:
- token
- - token, project, project_domain
+ - token, project_name, project_domain_id
- user_id, password
- - username, password, user_domain
- - username, password, project, user_domain, project_domain
+ - username, password, user_domain_id
+ - username, password, project_name, user_domain_id, project_domain_id
Validation is left to the server side.
"""
creds = {
@@ -68,25 +76,45 @@
id_obj['token'] = {
'id': token
}
- if user and password:
+
+ if (user_id or username) and password:
id_obj['methods'].append('password')
id_obj['password'] = {
'user': {
'password': password,
}
}
- if user_type == 'id':
- id_obj['password']['user']['id'] = user
+ if user_id:
+ id_obj['password']['user']['id'] = user_id
else:
- id_obj['password']['user']['name'] = user
- if user_domain is not None:
- _domain = dict(name=user_domain)
+ id_obj['password']['user']['name'] = username
+
+ _domain = None
+ if user_domain_id is not None:
+ _domain = dict(id=user_domain_id)
+ elif user_domain_name is not None:
+ _domain = dict(name=user_domain_name)
+ if _domain:
id_obj['password']['user']['domain'] = _domain
- if project is not None:
- _domain = dict(name=project_domain)
- _project = dict(name=project, domain=_domain)
- scope = dict(project=_project)
- creds['auth']['scope'] = scope
+
+ if (project_id or project_name):
+ _project = dict()
+
+ if project_id:
+ _project['id'] = project_id
+ elif project_name:
+ _project['name'] = project_name
+
+ if project_domain_id is not None:
+ _project['domain'] = {'id': project_domain_id}
+ elif project_domain_name is not None:
+ _project['domain'] = {'name': project_domain_name}
+
+ creds['auth']['scope'] = dict(project=_project)
+ elif domain_id:
+ creds['auth']['scope'] = dict(domain={'id': domain_id})
+ elif domain_name:
+ creds['auth']['scope'] = dict(domain={'name': domain_name})
body = json.dumps(creds)
resp, body = self.post(self.auth_url, body=body)
@@ -120,15 +148,22 @@
return resp, json.loads(resp_body)
- def get_token(self, user, password, project=None, project_domain='Default',
- user_domain='Default', auth_data=False):
+ def get_token(self, **kwargs):
"""
- :param user: username
Returns (token id, token data) for supplied credentials
"""
- body = self.auth(user, password, project, user_type='name',
- user_domain=user_domain,
- project_domain=project_domain)
+
+ auth_data = kwargs.pop('auth_data', False)
+
+ if not (kwargs.get('user_domain_id') or
+ kwargs.get('user_domain_name')):
+ kwargs['user_domain_name'] = 'Default'
+
+ if not (kwargs.get('project_domain_id') or
+ kwargs.get('project_domain_name')):
+ kwargs['project_domain_name'] = 'Default'
+
+ body = self.auth(**kwargs)
token = body.response.get('x-subject-token')
if auth_data:
diff --git a/tempest/tests/fake_credentials.py b/tempest/tests/fake_credentials.py
index 48f67d2..649d51d 100644
--- a/tempest/tests/fake_credentials.py
+++ b/tempest/tests/fake_credentials.py
@@ -43,7 +43,8 @@
username='fake_username',
password='fake_password',
user_domain_name='fake_domain_name',
- project_name='fake_tenant_name'
+ project_name='fake_tenant_name',
+ project_domain_name='fake_domain_name'
)
super(FakeKeystoneV3Credentials, self).__init__(**creds)