blob: 9bd437ed11a9198e67ac853a6d855de692f44a54 [file] [log] [blame]
ZhiQiang Fan39f97222013-09-20 04:49:44 +08001# Copyright 2012 OpenStack Foundation
Sean Dague6dbc6da2013-05-08 17:49:46 -04002# Copyright 2013 IBM Corp.
3# All Rights Reserved.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
Sean Dague6dbc6da2013-05-08 17:49:46 -040017import subprocess
18
Sean Dague6dbc6da2013-05-08 17:49:46 -040019import netaddr
Doug Hellmann583ce2c2015-03-11 14:55:46 +000020from oslo_log import log
Andrey Pavlovc8bd4b12015-08-17 10:20:17 +030021from oslo_serialization import jsonutils as json
Yatin Kumbhareee4924c2016-06-09 15:12:06 +053022from oslo_utils import netutils
Matthew Treinish96e9e882014-06-09 18:37:19 -040023import six
Sean Dague6dbc6da2013-05-08 17:49:46 -040024
lanoux5fc14522015-09-21 08:17:35 +000025from tempest.common import compute
Ken'ichi Ohmichi01151e82016-06-10 11:19:52 -070026from tempest.common import image as common_image
Fei Long Wangd39431f2015-05-14 11:30:48 +120027from tempest.common.utils import data_utils
Masayuki Igawa4ded9f02014-02-17 15:05:59 +090028from tempest.common.utils.linux import remote_client
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +000029from tempest.common import waiters
Matthew Treinish6c072292014-01-29 19:15:52 +000030from tempest import config
Giulio Fidente92f77192013-08-26 17:13:28 +020031from tempest import exceptions
Jordan Pittier9e227c52016-02-09 14:35:18 +010032from tempest.lib.common.utils import test_utils
Andrea Frittoli (andreaf)db9672e2016-02-23 14:07:24 -050033from tempest.lib import exceptions as lib_exc
Sean Dague6dbc6da2013-05-08 17:49:46 -040034import tempest.test
Sean Dague6dbc6da2013-05-08 17:49:46 -040035
Matthew Treinish6c072292014-01-29 19:15:52 +000036CONF = config.CONF
Sean Dague6dbc6da2013-05-08 17:49:46 -040037
Attila Fazekasfb7552a2013-08-27 13:02:26 +020038LOG = log.getLogger(__name__)
39
Sean Dague6dbc6da2013-05-08 17:49:46 -040040
Andrea Frittoli2e733b52014-07-16 14:12:11 +010041class ScenarioTest(tempest.test.BaseTestCase):
Andrea Frittoli486ede72014-09-25 11:50:05 +010042 """Base class for scenario tests. Uses tempest own clients. """
Andrea Frittoli2e733b52014-07-16 14:12:11 +010043
Andrea Frittolib21de6c2015-02-06 20:12:38 +000044 credentials = ['primary']
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +000045
46 @classmethod
47 def setup_clients(cls):
48 super(ScenarioTest, cls).setup_clients()
Andrea Frittoli247058f2014-07-16 16:09:22 +010049 # Clients (in alphabetical order)
Adam Gandelmanc78c7572014-08-28 18:38:55 -070050 cls.flavors_client = cls.manager.flavors_client
John Warrene74890a2015-11-11 15:18:01 -050051 cls.compute_floating_ips_client = (
52 cls.manager.compute_floating_ips_client)
Jordan Pittier1d2e40f2016-01-05 18:49:14 +010053 if CONF.service_available.glance:
Matt Riedemann2aa19d42016-06-06 17:45:41 -040054 # Check if glance v1 is available to determine which client to use.
55 if CONF.image_feature_enabled.api_v1:
56 cls.image_client = cls.manager.image_client
57 elif CONF.image_feature_enabled.api_v2:
58 cls.image_client = cls.manager.image_client_v2
59 else:
60 raise exceptions.InvalidConfiguration(
61 'Either api_v1 or api_v2 must be True in '
62 '[image-feature-enabled].')
nithya-ganesan882595e2014-07-29 18:51:07 +000063 # Compute image client
Ghanshyamae76c122015-12-22 13:41:35 +090064 cls.compute_images_client = cls.manager.compute_images_client
Andrea Frittoli247058f2014-07-16 16:09:22 +010065 cls.keypairs_client = cls.manager.keypairs_client
Andrea Frittoli247058f2014-07-16 16:09:22 +010066 # Nova security groups client
John Warrenf2345512015-12-10 13:39:30 -050067 cls.compute_security_groups_client = (
68 cls.manager.compute_security_groups_client)
John Warren5cdbf422016-01-05 12:42:43 -050069 cls.compute_security_group_rules_client = (
70 cls.manager.compute_security_group_rules_client)
Andrea Frittoli247058f2014-07-16 16:09:22 +010071 cls.servers_client = cls.manager.servers_client
Yair Fried1fc32a12014-08-04 09:11:30 +030072 cls.interface_client = cls.manager.interfaces_client
73 # Neutron network client
John Warren94d8faf2015-09-15 12:22:24 -040074 cls.networks_client = cls.manager.networks_client
John Warren49c0fe52015-10-22 12:35:54 -040075 cls.ports_client = cls.manager.ports_client
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +000076 cls.routers_client = cls.manager.routers_client
John Warren3961acd2015-10-02 14:38:53 -040077 cls.subnets_client = cls.manager.subnets_client
John Warrenfbf2a892015-11-17 12:36:14 -050078 cls.floating_ips_client = cls.manager.floating_ips_client
John Warrenf9606e92015-12-10 12:12:42 -050079 cls.security_groups_client = cls.manager.security_groups_client
John Warren456d9ae2016-01-12 15:36:33 -050080 cls.security_group_rules_client = (
81 cls.manager.security_group_rules_client)
Andrea Frittoli2e733b52014-07-16 14:12:11 +010082
Ivan Kolodyazhnybcfc32e2015-08-06 13:31:36 +030083 if CONF.volume_feature_enabled.api_v1:
84 cls.volumes_client = cls.manager.volumes_client
85 cls.snapshots_client = cls.manager.snapshots_client
86 else:
87 cls.volumes_client = cls.manager.volumes_v2_client
88 cls.snapshots_client = cls.manager.snapshots_v2_client
89
Andrea Frittoli247058f2014-07-16 16:09:22 +010090 # ## Methods to handle sync and async deletes
91
92 def setUp(self):
93 super(ScenarioTest, self).setUp()
94 self.cleanup_waits = []
95 # NOTE(mtreinish) This is safe to do in setUp instead of setUp class
96 # because scenario tests in the same test class should not share
97 # resources. If resources were shared between test cases then it
98 # should be a single scenario test instead of multiples.
99
100 # NOTE(yfried): this list is cleaned at the end of test_methods and
101 # not at the end of the class
102 self.addCleanup(self._wait_for_cleanups)
103
Andrea Frittoli247058f2014-07-16 16:09:22 +0100104 def addCleanup_with_wait(self, waiter_callable, thing_id, thing_id_param,
Ghanshyam2a180b82014-06-16 13:54:22 +0900105 cleanup_callable, cleanup_args=None,
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000106 cleanup_kwargs=None, waiter_client=None):
Adam Gandelmanc78c7572014-08-28 18:38:55 -0700107 """Adds wait for async resource deletion at the end of cleanups
Andrea Frittoli247058f2014-07-16 16:09:22 +0100108
109 @param waiter_callable: callable to wait for the resource to delete
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000110 with the following waiter_client if specified.
Andrea Frittoli247058f2014-07-16 16:09:22 +0100111 @param thing_id: the id of the resource to be cleaned-up
112 @param thing_id_param: the name of the id param in the waiter
113 @param cleanup_callable: method to load pass to self.addCleanup with
114 the following *cleanup_args, **cleanup_kwargs.
115 usually a delete method.
116 """
Ghanshyam2a180b82014-06-16 13:54:22 +0900117 if cleanup_args is None:
118 cleanup_args = []
119 if cleanup_kwargs is None:
120 cleanup_kwargs = {}
Andrea Frittoli247058f2014-07-16 16:09:22 +0100121 self.addCleanup(cleanup_callable, *cleanup_args, **cleanup_kwargs)
122 wait_dict = {
123 'waiter_callable': waiter_callable,
124 thing_id_param: thing_id
125 }
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000126 if waiter_client:
127 wait_dict['client'] = waiter_client
Andrea Frittoli247058f2014-07-16 16:09:22 +0100128 self.cleanup_waits.append(wait_dict)
129
130 def _wait_for_cleanups(self):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000131 # To handle async delete actions, a list of waits is added
132 # which will be iterated over as the last step of clearing the
133 # cleanup queue. That way all the delete calls are made up front
134 # and the tests won't succeed unless the deletes are eventually
135 # successful. This is the same basic approach used in the api tests to
136 # limit cleanup execution time except here it is multi-resource,
137 # because of the nature of the scenario tests.
Andrea Frittoli247058f2014-07-16 16:09:22 +0100138 for wait in self.cleanup_waits:
139 waiter_callable = wait.pop('waiter_callable')
140 waiter_callable(**wait)
141
142 # ## Test functions library
143 #
144 # The create_[resource] functions only return body and discard the
145 # resp part which is not used in scenario tests
146
Yair Frieddb6c9e92014-08-06 08:53:13 +0300147 def create_keypair(self, client=None):
148 if not client:
149 client = self.keypairs_client
Andrea Frittoli247058f2014-07-16 16:09:22 +0100150 name = data_utils.rand_name(self.__class__.__name__)
151 # We don't need to create a keypair by pubkey in scenario
Ken'ichi Ohmichie364bce2015-07-17 10:27:59 +0000152 body = client.create_keypair(name=name)
Yair Frieddb6c9e92014-08-06 08:53:13 +0300153 self.addCleanup(client.delete_keypair, name)
ghanshyamdee01f22015-08-17 11:41:47 +0900154 return body['keypair']
Andrea Frittoli247058f2014-07-16 16:09:22 +0100155
Anusha Ramineni9aaef8b2016-01-19 10:56:40 +0530156 def create_server(self, name=None, image_id=None, flavor=None,
lanoux5fc14522015-09-21 08:17:35 +0000157 validatable=False, wait_until=None,
158 wait_on_delete=True, clients=None, **kwargs):
159 """Wrapper utility that returns a test server.
Andrea Frittoli247058f2014-07-16 16:09:22 +0100160
lanoux5fc14522015-09-21 08:17:35 +0000161 This wrapper utility calls the common create test server and
162 returns a test server. The purpose of this wrapper is to minimize
163 the impact on the code of the tests already using this
164 function.
Andrea Frittoli247058f2014-07-16 16:09:22 +0100165 """
Andrea Frittoli247058f2014-07-16 16:09:22 +0100166
lanoux5fc14522015-09-21 08:17:35 +0000167 # NOTE(jlanoux): As a first step, ssh checks in the scenario
168 # tests need to be run regardless of the run_validation and
169 # validatable parameters and thus until the ssh validation job
170 # becomes voting in CI. The test resources management and IP
171 # association are taken care of in the scenario tests.
172 # Therefore, the validatable parameter is set to false in all
173 # those tests. In this way create_server just return a standard
174 # server and the scenario tests always perform ssh checks.
175
176 # Needed for the cross_tenant_traffic test:
177 if clients is None:
178 clients = self.manager
179
180 vnic_type = CONF.network.port_vnic_type
181
182 # If vnic_type is configured create port for
183 # every network
184 if vnic_type:
185 ports = []
186 networks = []
187 create_port_body = {'binding:vnic_type': vnic_type,
188 'namestart': 'port-smoke'}
189 if kwargs:
190 # Convert security group names to security group ids
191 # to pass to create_port
192 if 'security_groups' in kwargs:
193 security_groups =\
John Warrenf9606e92015-12-10 12:12:42 -0500194 clients.security_groups_client.list_security_groups(
lanoux5fc14522015-09-21 08:17:35 +0000195 ).get('security_groups')
196 sec_dict = dict([(s['name'], s['id'])
197 for s in security_groups])
198
199 sec_groups_names = [s['name'] for s in kwargs.pop(
200 'security_groups')]
201 security_groups_ids = [sec_dict[s]
202 for s in sec_groups_names]
203
204 if security_groups_ids:
205 create_port_body[
206 'security_groups'] = security_groups_ids
207 networks = kwargs.pop('networks')
208
209 # If there are no networks passed to us we look up
Sean Dagueed6e5862016-04-04 10:49:13 -0400210 # for the project's private networks and create a port
lanoux5fc14522015-09-21 08:17:35 +0000211 # if there is only one private network. The same behaviour
212 # as we would expect when passing the call to the clients
213 # with no networks
214 if not networks:
215 networks = clients.networks_client.list_networks(
216 filters={'router:external': False})
217 self.assertEqual(1, len(networks),
218 "There is more than one"
219 " network for the tenant")
220 for net in networks:
221 net_id = net['uuid']
222 port = self._create_port(network_id=net_id,
223 client=clients.ports_client,
224 **create_port_body)
Lenny Verkhovsky92530472016-06-16 09:14:25 +0300225 ports.append({'port': port['id']})
lanoux5fc14522015-09-21 08:17:35 +0000226 if ports:
227 kwargs['networks'] = ports
228 self.ports = ports
229
230 tenant_network = self.get_tenant_network()
231
232 body, servers = compute.create_test_server(
233 clients,
234 tenant_network=tenant_network,
235 wait_until=wait_until,
Anusha Ramineni9aaef8b2016-01-19 10:56:40 +0530236 name=name, flavor=flavor,
237 image_id=image_id, **kwargs)
lanoux5fc14522015-09-21 08:17:35 +0000238
239 # TODO(jlanoux) Move wait_on_delete in compute.py
Andrea Frittoli247058f2014-07-16 16:09:22 +0100240 if wait_on_delete:
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000241 self.addCleanup(waiters.wait_for_server_termination,
lanoux5fc14522015-09-21 08:17:35 +0000242 clients.servers_client,
243 body['id'])
244
Andrea Frittoli247058f2014-07-16 16:09:22 +0100245 self.addCleanup_with_wait(
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000246 waiter_callable=waiters.wait_for_server_termination,
lanoux5fc14522015-09-21 08:17:35 +0000247 thing_id=body['id'], thing_id_param='server_id',
Jordan Pittier9e227c52016-02-09 14:35:18 +0100248 cleanup_callable=test_utils.call_and_ignore_notfound_exc,
lanoux5fc14522015-09-21 08:17:35 +0000249 cleanup_args=[clients.servers_client.delete_server, body['id']],
250 waiter_client=clients.servers_client)
251 server = clients.servers_client.show_server(body['id'])['server']
Andrea Frittoli247058f2014-07-16 16:09:22 +0100252 return server
253
Markus Zoeller3d2a21c2015-02-27 12:04:22 +0100254 def create_volume(self, size=None, name=None, snapshot_id=None,
Jordan Pittier5e1741c2016-03-02 18:25:51 +0100255 imageRef=None, volume_type=None):
Andrea Frittoli247058f2014-07-16 16:09:22 +0100256 if name is None:
257 name = data_utils.rand_name(self.__class__.__name__)
Ghanshyam8fc0ed22015-12-18 10:25:14 +0900258 kwargs = {'display_name': name,
259 'snapshot_id': snapshot_id,
260 'imageRef': imageRef,
261 'volume_type': volume_type}
262 if size is not None:
263 kwargs.update({'size': size})
264 volume = self.volumes_client.create_volume(**kwargs)['volume']
Matt Riedemanne85c2702014-09-10 11:50:13 -0700265
Jordan Pittier5e1741c2016-03-02 18:25:51 +0100266 self.addCleanup(self.volumes_client.wait_for_resource_deletion,
267 volume['id'])
Jordan Pittier9e227c52016-02-09 14:35:18 +0100268 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
Jordan Pittier5e1741c2016-03-02 18:25:51 +0100269 self.volumes_client.delete_volume, volume['id'])
Andrea Frittoli247058f2014-07-16 16:09:22 +0100270
Ivan Kolodyazhnybcfc32e2015-08-06 13:31:36 +0300271 # NOTE(e0ne): Cinder API v2 uses name instead of display_name
272 if 'display_name' in volume:
273 self.assertEqual(name, volume['display_name'])
274 else:
275 self.assertEqual(name, volume['name'])
Yaroslav Lobankoved3a35b2016-03-24 22:41:30 -0500276 waiters.wait_for_volume_status(self.volumes_client,
277 volume['id'], 'available')
Andrea Frittoli247058f2014-07-16 16:09:22 +0100278 # The volume retrieved on creation has a non-up-to-date status.
279 # Retrieval after it becomes active ensures correct details.
John Warren6177c9e2015-08-19 20:00:17 +0000280 volume = self.volumes_client.show_volume(volume['id'])['volume']
Andrea Frittoli247058f2014-07-16 16:09:22 +0100281 return volume
282
Yair Fried1fc32a12014-08-04 09:11:30 +0300283 def _create_loginable_secgroup_rule(self, secgroup_id=None):
John Warrenf2345512015-12-10 13:39:30 -0500284 _client = self.compute_security_groups_client
John Warren5cdbf422016-01-05 12:42:43 -0500285 _client_rules = self.compute_security_group_rules_client
Andrea Frittoli247058f2014-07-16 16:09:22 +0100286 if secgroup_id is None:
ghanshyamb610b772015-08-24 17:29:38 +0900287 sgs = _client.list_security_groups()['security_groups']
Andrea Frittoli247058f2014-07-16 16:09:22 +0100288 for sg in sgs:
289 if sg['name'] == 'default':
290 secgroup_id = sg['id']
291
292 # These rules are intended to permit inbound ssh and icmp
293 # traffic from all sources, so no group_id is provided.
294 # Setting a group_id would only permit traffic from ports
295 # belonging to the same security group.
296 rulesets = [
297 {
298 # ssh
Ken'ichi Ohmichieb7eeec2015-07-21 01:00:06 +0000299 'ip_protocol': 'tcp',
Andrea Frittoli247058f2014-07-16 16:09:22 +0100300 'from_port': 22,
301 'to_port': 22,
302 'cidr': '0.0.0.0/0',
303 },
304 {
305 # ping
Ken'ichi Ohmichieb7eeec2015-07-21 01:00:06 +0000306 'ip_protocol': 'icmp',
Andrea Frittoli247058f2014-07-16 16:09:22 +0100307 'from_port': -1,
308 'to_port': -1,
309 'cidr': '0.0.0.0/0',
310 }
311 ]
312 rules = list()
313 for ruleset in rulesets:
Ken'ichi Ohmichieb7eeec2015-07-21 01:00:06 +0000314 sg_rule = _client_rules.create_security_group_rule(
ghanshyam0a5e1232015-08-24 16:59:59 +0900315 parent_group_id=secgroup_id, **ruleset)['security_group_rule']
Andrea Frittoli247058f2014-07-16 16:09:22 +0100316 rules.append(sg_rule)
317 return rules
318
Yair Fried1fc32a12014-08-04 09:11:30 +0300319 def _create_security_group(self):
Andrea Frittoli247058f2014-07-16 16:09:22 +0100320 # Create security group
321 sg_name = data_utils.rand_name(self.__class__.__name__)
322 sg_desc = sg_name + " description"
John Warrenf2345512015-12-10 13:39:30 -0500323 secgroup = self.compute_security_groups_client.create_security_group(
ghanshyamb610b772015-08-24 17:29:38 +0900324 name=sg_name, description=sg_desc)['security_group']
Andrea Frittoli247058f2014-07-16 16:09:22 +0100325 self.assertEqual(secgroup['name'], sg_name)
326 self.assertEqual(secgroup['description'], sg_desc)
John Warrenf2345512015-12-10 13:39:30 -0500327 self.addCleanup(
Jordan Pittier9e227c52016-02-09 14:35:18 +0100328 test_utils.call_and_ignore_notfound_exc,
John Warrenf2345512015-12-10 13:39:30 -0500329 self.compute_security_groups_client.delete_security_group,
330 secgroup['id'])
Andrea Frittoli247058f2014-07-16 16:09:22 +0100331
332 # Add rules to the security group
Yair Fried1fc32a12014-08-04 09:11:30 +0300333 self._create_loginable_secgroup_rule(secgroup['id'])
Andrea Frittoli247058f2014-07-16 16:09:22 +0100334
335 return secgroup
336
Sean Dague20e98612016-01-06 14:33:28 -0500337 def get_remote_client(self, ip_address, username=None, private_key=None):
JordanP3fe2dc32014-11-17 13:06:01 +0100338 """Get a SSH client to a remote server
339
Sean Dague20e98612016-01-06 14:33:28 -0500340 @param ip_address the server floating or fixed IP address to use
341 for ssh validation
JordanP3fe2dc32014-11-17 13:06:01 +0100342 @param username name of the Linux account on the remote server
343 @param private_key the SSH private key to use
JordanP3fe2dc32014-11-17 13:06:01 +0100344 @return a RemoteClient object
345 """
Adam Gandelmanc78c7572014-08-28 18:38:55 -0700346
Andrea Frittoli247058f2014-07-16 16:09:22 +0100347 if username is None:
lanoux283273b2015-12-04 03:01:54 -0800348 username = CONF.validation.image_ssh_user
wantwatering896300c2015-03-27 15:17:42 +0800349 # Set this with 'keypair' or others to log in with keypair or
350 # username/password.
lanoux5fc14522015-09-21 08:17:35 +0000351 if CONF.validation.auth_method == 'keypair':
wantwatering896300c2015-03-27 15:17:42 +0800352 password = None
353 if private_key is None:
354 private_key = self.keypair['private_key']
355 else:
lanoux283273b2015-12-04 03:01:54 -0800356 password = CONF.validation.image_ssh_password
wantwatering896300c2015-03-27 15:17:42 +0800357 private_key = None
Sean Dague20e98612016-01-06 14:33:28 -0500358 linux_client = remote_client.RemoteClient(ip_address, username,
wantwatering896300c2015-03-27 15:17:42 +0800359 pkey=private_key,
360 password=password)
Andrea Frittoli247058f2014-07-16 16:09:22 +0100361 try:
362 linux_client.validate_authentication()
Matt Riedemann5f0ac522015-05-21 09:16:24 -0700363 except Exception as e:
364 message = ('Initializing SSH connection to %(ip)s failed. '
Eric Brown0911af62016-02-08 17:15:40 -0800365 'Error: %(error)s' % {'ip': ip_address,
Sean Dague20e98612016-01-06 14:33:28 -0500366 'error': e})
Jordan Pittier9e227c52016-02-09 14:35:18 +0100367 caller = test_utils.find_test_caller()
Matt Riedemann5f0ac522015-05-21 09:16:24 -0700368 if caller:
369 message = '(%s) %s' % (caller, message)
370 LOG.exception(message)
Sean Dague2c98a162016-01-06 14:11:13 -0500371 self._log_console_output()
Andrea Frittoli247058f2014-07-16 16:09:22 +0100372 raise
373
374 return linux_client
375
Evgeny Antyshev7ba0d5f2015-04-28 13:18:07 +0000376 def _image_create(self, name, fmt, path,
377 disk_format=None, properties=None):
Ghanshyam2a180b82014-06-16 13:54:22 +0900378 if properties is None:
379 properties = {}
Andrea Frittoli247058f2014-07-16 16:09:22 +0100380 name = data_utils.rand_name('%s-' % name)
Andrea Frittoli247058f2014-07-16 16:09:22 +0100381 params = {
382 'name': name,
383 'container_format': fmt,
Evgeny Antyshev7ba0d5f2015-04-28 13:18:07 +0000384 'disk_format': disk_format or fmt,
Andrea Frittoli247058f2014-07-16 16:09:22 +0100385 }
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400386 if CONF.image_feature_enabled.api_v1:
387 params['is_public'] = 'False'
388 params['properties'] = properties
Ken'ichi Ohmichi02bcdf32016-06-17 16:41:26 -0700389 params = {'headers': common_image.image_meta_to_headers(**params)}
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400390 else:
391 params['visibility'] = 'private'
392 # Additional properties are flattened out in the v2 API.
393 params.update(properties)
394 body = self.image_client.create_image(**params)
395 image = body['image'] if 'image' in body else body
Andrea Frittoli247058f2014-07-16 16:09:22 +0100396 self.addCleanup(self.image_client.delete_image, image['id'])
397 self.assertEqual("queued", image['status'])
zhang.leia4b1cef2016-03-01 10:50:01 +0800398 with open(path, 'rb') as image_file:
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400399 if CONF.image_feature_enabled.api_v1:
400 self.image_client.update_image(image['id'], data=image_file)
401 else:
402 self.image_client.store_image_file(image['id'], image_file)
Andrea Frittoli247058f2014-07-16 16:09:22 +0100403 return image['id']
404
405 def glance_image_create(self):
Alessandro Pilottib7c1daa2014-08-16 14:24:13 +0300406 img_path = CONF.scenario.img_dir + "/" + CONF.scenario.img_file
Andrea Frittoli247058f2014-07-16 16:09:22 +0100407 aki_img_path = CONF.scenario.img_dir + "/" + CONF.scenario.aki_img_file
408 ari_img_path = CONF.scenario.img_dir + "/" + CONF.scenario.ari_img_file
409 ami_img_path = CONF.scenario.img_dir + "/" + CONF.scenario.ami_img_file
Alessandro Pilottib7c1daa2014-08-16 14:24:13 +0300410 img_container_format = CONF.scenario.img_container_format
411 img_disk_format = CONF.scenario.img_disk_format
Evgeny Antyshev7ba0d5f2015-04-28 13:18:07 +0000412 img_properties = CONF.scenario.img_properties
PranaliD2aa523c2016-06-07 03:54:34 -0400413 LOG.debug("paths: img: %s, container_format: %s, disk_format: %s, "
Evgeny Antyshev7ba0d5f2015-04-28 13:18:07 +0000414 "properties: %s, ami: %s, ari: %s, aki: %s" %
Alessandro Pilottib7c1daa2014-08-16 14:24:13 +0300415 (img_path, img_container_format, img_disk_format,
Evgeny Antyshev7ba0d5f2015-04-28 13:18:07 +0000416 img_properties, ami_img_path, ari_img_path, aki_img_path))
Andrea Frittoli247058f2014-07-16 16:09:22 +0100417 try:
Jordan Pittier1e443ec2015-11-20 16:15:58 +0100418 image = self._image_create('scenario-img',
419 img_container_format,
420 img_path,
421 disk_format=img_disk_format,
422 properties=img_properties)
Andrea Frittoli247058f2014-07-16 16:09:22 +0100423 except IOError:
424 LOG.debug("A qcow2 image was not found. Try to get a uec image.")
425 kernel = self._image_create('scenario-aki', 'aki', aki_img_path)
426 ramdisk = self._image_create('scenario-ari', 'ari', ari_img_path)
Evgeny Antyshev7ba0d5f2015-04-28 13:18:07 +0000427 properties = {'kernel_id': kernel, 'ramdisk_id': ramdisk}
Jordan Pittier1e443ec2015-11-20 16:15:58 +0100428 image = self._image_create('scenario-ami', 'ami',
429 path=ami_img_path,
430 properties=properties)
431 LOG.debug("image:%s" % image)
432
433 return image
Andrea Frittoli247058f2014-07-16 16:09:22 +0100434
435 def _log_console_output(self, servers=None):
Matthew Treinish42a3f3a2014-09-04 15:04:53 -0400436 if not CONF.compute_feature_enabled.console_output:
437 LOG.debug('Console output not supported, cannot log')
438 return
Andrea Frittoli247058f2014-07-16 16:09:22 +0100439 if not servers:
David Kranzae99b9a2015-02-16 13:37:01 -0500440 servers = self.servers_client.list_servers()
Andrea Frittoli247058f2014-07-16 16:09:22 +0100441 servers = servers['servers']
442 for server in servers:
Brant Knudson566c5712014-09-24 20:04:50 -0500443 console_output = self.servers_client.get_console_output(
Ken'ichi Ohmichibf4766a2015-12-09 07:48:43 +0000444 server['id'])['output']
David Kranzae99b9a2015-02-16 13:37:01 -0500445 LOG.debug('Console output for %s\nbody=\n%s',
446 server['id'], console_output)
Andrea Frittoli247058f2014-07-16 16:09:22 +0100447
Ken'ichi Ohmichi6e201f52014-10-01 04:21:39 +0000448 def _log_net_info(self, exc):
449 # network debug is called as part of ssh init
Andrey Pavlov64723762015-04-29 06:24:58 +0300450 if not isinstance(exc, lib_exc.SSHTimeout):
Ken'ichi Ohmichi6e201f52014-10-01 04:21:39 +0000451 LOG.debug('Network information on a devstack host')
Ken'ichi Ohmichi6e201f52014-10-01 04:21:39 +0000452
nithya-ganesan882595e2014-07-29 18:51:07 +0000453 def create_server_snapshot(self, server, name=None):
454 # Glance client
455 _image_client = self.image_client
456 # Compute client
Ghanshyamae76c122015-12-22 13:41:35 +0900457 _images_client = self.compute_images_client
nithya-ganesan882595e2014-07-29 18:51:07 +0000458 if name is None:
Ken'ichi Ohmichi6ded8df2015-03-23 02:00:19 +0000459 name = data_utils.rand_name('scenario-snapshot')
nithya-ganesan882595e2014-07-29 18:51:07 +0000460 LOG.debug("Creating a snapshot image for server: %s", server['name'])
Ken'ichi Ohmichi28f18672015-07-17 10:00:38 +0000461 image = _images_client.create_image(server['id'], name=name)
David Kranza5299eb2015-01-15 17:24:05 -0500462 image_id = image.response['location'].split('images/')[1]
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +0300463 waiters.wait_for_image_status(_image_client, image_id, 'active')
nithya-ganesan882595e2014-07-29 18:51:07 +0000464 self.addCleanup_with_wait(
465 waiter_callable=_image_client.wait_for_resource_deletion,
466 thing_id=image_id, thing_id_param='id',
Jordan Pittier9e227c52016-02-09 14:35:18 +0100467 cleanup_callable=test_utils.call_and_ignore_notfound_exc,
nithya-ganesan882595e2014-07-29 18:51:07 +0000468 cleanup_args=[_image_client.delete_image, image_id])
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400469 if CONF.image_feature_enabled.api_v1:
470 # In glance v1 the additional properties are stored in the headers.
Ken'ichi Ohmichi01151e82016-06-10 11:19:52 -0700471 resp = _image_client.check_image(image_id)
472 snapshot_image = common_image.get_image_meta_from_headers(resp)
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400473 image_props = snapshot_image.get('properties', {})
474 else:
475 # In glance v2 the additional properties are flattened.
476 snapshot_image = _image_client.show_image(image_id)
477 image_props = snapshot_image
Andrey Pavlovc8bd4b12015-08-17 10:20:17 +0300478
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400479 bdm = image_props.get('block_device_mapping')
Andrey Pavlovc8bd4b12015-08-17 10:20:17 +0300480 if bdm:
481 bdm = json.loads(bdm)
482 if bdm and 'snapshot_id' in bdm[0]:
483 snapshot_id = bdm[0]['snapshot_id']
484 self.addCleanup(
485 self.snapshots_client.wait_for_resource_deletion,
486 snapshot_id)
Jordan Pittier9e227c52016-02-09 14:35:18 +0100487 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
488 self.snapshots_client.delete_snapshot,
489 snapshot_id)
Yaroslav Lobankov667aaa22016-03-24 23:13:28 -0500490 waiters.wait_for_snapshot_status(self.snapshots_client,
491 snapshot_id, 'available')
nithya-ganesan882595e2014-07-29 18:51:07 +0000492 image_name = snapshot_image['name']
493 self.assertEqual(name, image_name)
494 LOG.debug("Created snapshot image %s for server %s",
495 image_name, server['name'])
496 return snapshot_image
497
Jordan Pittier7cf64762015-10-14 15:01:12 +0200498 def nova_volume_attach(self, server, volume_to_attach):
Joseph Lanoux6809bab2014-12-18 14:57:18 +0000499 volume = self.servers_client.attach_volume(
Jordan Pittier7cf64762015-10-14 15:01:12 +0200500 server['id'], volumeId=volume_to_attach['id'], device='/dev/%s'
ghanshyam0f825252015-08-25 16:02:50 +0900501 % CONF.compute.volume_device_name)['volumeAttachment']
Jordan Pittier7cf64762015-10-14 15:01:12 +0200502 self.assertEqual(volume_to_attach['id'], volume['id'])
Yaroslav Lobankoved3a35b2016-03-24 22:41:30 -0500503 waiters.wait_for_volume_status(self.volumes_client,
504 volume['id'], 'in-use')
Masayuki Igawa1f0ad632014-08-05 13:36:56 +0900505
Jordan Pittier7cf64762015-10-14 15:01:12 +0200506 # Return the updated volume after the attachment
507 return self.volumes_client.show_volume(volume['id'])['volume']
Masayuki Igawa1f0ad632014-08-05 13:36:56 +0900508
Jordan Pittier7cf64762015-10-14 15:01:12 +0200509 def nova_volume_detach(self, server, volume):
510 self.servers_client.detach_volume(server['id'], volume['id'])
Yaroslav Lobankoved3a35b2016-03-24 22:41:30 -0500511 waiters.wait_for_volume_status(self.volumes_client,
512 volume['id'], 'available')
Jordan Pittier7cf64762015-10-14 15:01:12 +0200513
514 volume = self.volumes_client.show_volume(volume['id'])['volume']
Masayuki Igawa1f0ad632014-08-05 13:36:56 +0900515 self.assertEqual('available', volume['status'])
516
Adam Gandelmanc78c7572014-08-28 18:38:55 -0700517 def rebuild_server(self, server_id, image=None,
518 preserve_ephemeral=False, wait=True,
519 rebuild_kwargs=None):
520 if image is None:
521 image = CONF.compute.image_ref
522
523 rebuild_kwargs = rebuild_kwargs or {}
524
525 LOG.debug("Rebuilding server (id: %s, image: %s, preserve eph: %s)",
526 server_id, image, preserve_ephemeral)
Ken'ichi Ohmichi5271b0f2015-08-10 07:53:27 +0000527 self.servers_client.rebuild_server(
528 server_id=server_id, image_ref=image,
529 preserve_ephemeral=preserve_ephemeral,
530 **rebuild_kwargs)
Adam Gandelmanc78c7572014-08-28 18:38:55 -0700531 if wait:
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000532 waiters.wait_for_server_status(self.servers_client,
533 server_id, 'ACTIVE')
Adam Gandelmanc78c7572014-08-28 18:38:55 -0700534
Steven Hardyda2a8352014-10-02 12:52:20 +0100535 def ping_ip_address(self, ip_address, should_succeed=True,
536 ping_timeout=None):
lanoux5fc14522015-09-21 08:17:35 +0000537 timeout = ping_timeout or CONF.validation.ping_timeout
Aaron Rosena7df13b2014-09-23 09:45:45 -0700538 cmd = ['ping', '-c1', '-w1', ip_address]
539
540 def ping():
541 proc = subprocess.Popen(cmd,
542 stdout=subprocess.PIPE,
543 stderr=subprocess.PIPE)
544 proc.communicate()
Shuquan Huang753629e2015-07-20 08:52:29 +0000545
Aaron Rosena7df13b2014-09-23 09:45:45 -0700546 return (proc.returncode == 0) == should_succeed
547
Jordan Pittier9e227c52016-02-09 14:35:18 +0100548 caller = test_utils.find_test_caller()
Shuquan Huang753629e2015-07-20 08:52:29 +0000549 LOG.debug('%(caller)s begins to ping %(ip)s in %(timeout)s sec and the'
550 ' expected result is %(should_succeed)s' % {
551 'caller': caller, 'ip': ip_address, 'timeout': timeout,
552 'should_succeed':
553 'reachable' if should_succeed else 'unreachable'
554 })
555 result = tempest.test.call_until_true(ping, timeout, 1)
556 LOG.debug('%(caller)s finishes ping %(ip)s in %(timeout)s sec and the '
557 'ping result is %(result)s' % {
558 'caller': caller, 'ip': ip_address, 'timeout': timeout,
559 'result': 'expected' if result else 'unexpected'
560 })
561 return result
Aaron Rosena7df13b2014-09-23 09:45:45 -0700562
Yair Friedae0e73d2014-11-24 11:56:26 +0200563 def check_vm_connectivity(self, ip_address,
564 username=None,
565 private_key=None,
566 should_connect=True):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000567 """Check server connectivity
568
Yair Friedae0e73d2014-11-24 11:56:26 +0200569 :param ip_address: server to test against
570 :param username: server's ssh username
571 :param private_key: server's ssh private key to be used
572 :param should_connect: True/False indicates positive/negative test
573 positive - attempt ping and ssh
574 negative - attempt ping and fail if succeed
575
576 :raises: AssertError if the result of the connectivity check does
577 not match the value of the should_connect param
578 """
579 if should_connect:
580 msg = "Timed out waiting for %s to become reachable" % ip_address
581 else:
582 msg = "ip address %s is reachable" % ip_address
583 self.assertTrue(self.ping_ip_address(ip_address,
584 should_succeed=should_connect),
585 msg=msg)
586 if should_connect:
587 # no need to check ssh for negative connectivity
588 self.get_remote_client(ip_address, username, private_key)
589
590 def check_public_network_connectivity(self, ip_address, username,
591 private_key, should_connect=True,
592 msg=None, servers=None):
593 # The target login is assumed to have been configured for
594 # key-based authentication by cloud-init.
595 LOG.debug('checking network connections to IP %s with user: %s' %
596 (ip_address, username))
597 try:
598 self.check_vm_connectivity(ip_address,
599 username,
600 private_key,
601 should_connect=should_connect)
Matthew Treinish53483132014-12-09 18:50:06 -0500602 except Exception:
Yair Friedae0e73d2014-11-24 11:56:26 +0200603 ex_msg = 'Public network connectivity check failed'
604 if msg:
605 ex_msg += ": " + msg
606 LOG.exception(ex_msg)
607 self._log_console_output(servers)
Yair Friedae0e73d2014-11-24 11:56:26 +0200608 raise
609
610 def create_floating_ip(self, thing, pool_name=None):
Ken'ichi Ohmichia112a592015-11-17 08:49:37 +0000611 """Create a floating IP and associates to a server on Nova"""
Yair Friedae0e73d2014-11-24 11:56:26 +0200612
Marc Koderer3b57d802016-03-22 15:23:31 +0100613 if not pool_name:
614 pool_name = CONF.network.floating_network_name
John Warrene74890a2015-11-11 15:18:01 -0500615 floating_ip = (self.compute_floating_ips_client.
Ken'ichi Ohmichie037a6f2015-12-03 06:41:49 +0000616 create_floating_ip(pool=pool_name)['floating_ip'])
Jordan Pittier9e227c52016-02-09 14:35:18 +0100617 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
John Warrene74890a2015-11-11 15:18:01 -0500618 self.compute_floating_ips_client.delete_floating_ip,
Yair Friedae0e73d2014-11-24 11:56:26 +0200619 floating_ip['id'])
John Warrene74890a2015-11-11 15:18:01 -0500620 self.compute_floating_ips_client.associate_floating_ip_to_server(
Yair Friedae0e73d2014-11-24 11:56:26 +0200621 floating_ip['ip'], thing['id'])
622 return floating_ip
623
Sean Dague20e98612016-01-06 14:33:28 -0500624 def create_timestamp(self, ip_address, dev_name=None, mount_path='/mnt',
Matt Riedemannfd5657d2015-09-30 14:47:07 -0700625 private_key=None):
Sean Dague20e98612016-01-06 14:33:28 -0500626 ssh_client = self.get_remote_client(ip_address,
Matt Riedemannfd5657d2015-09-30 14:47:07 -0700627 private_key=private_key)
Alexander Gubanovabd154c2015-09-23 23:24:06 +0300628 if dev_name is not None:
629 ssh_client.make_fs(dev_name)
Matt Riedemann076685a2015-09-30 14:38:16 -0700630 ssh_client.mount(dev_name, mount_path)
Alexander Gubanovabd154c2015-09-23 23:24:06 +0300631 cmd_timestamp = 'sudo sh -c "date > %s/timestamp; sync"' % mount_path
632 ssh_client.exec_command(cmd_timestamp)
633 timestamp = ssh_client.exec_command('sudo cat %s/timestamp'
634 % mount_path)
635 if dev_name is not None:
636 ssh_client.umount(mount_path)
637 return timestamp
638
Sean Dague20e98612016-01-06 14:33:28 -0500639 def get_timestamp(self, ip_address, dev_name=None, mount_path='/mnt',
Matt Riedemannfd5657d2015-09-30 14:47:07 -0700640 private_key=None):
Sean Dague20e98612016-01-06 14:33:28 -0500641 ssh_client = self.get_remote_client(ip_address,
Matt Riedemannfd5657d2015-09-30 14:47:07 -0700642 private_key=private_key)
Alexander Gubanovabd154c2015-09-23 23:24:06 +0300643 if dev_name is not None:
Matt Riedemann076685a2015-09-30 14:38:16 -0700644 ssh_client.mount(dev_name, mount_path)
Alexander Gubanovabd154c2015-09-23 23:24:06 +0300645 timestamp = ssh_client.exec_command('sudo cat %s/timestamp'
646 % mount_path)
647 if dev_name is not None:
648 ssh_client.umount(mount_path)
649 return timestamp
650
Sean Dague20e98612016-01-06 14:33:28 -0500651 def get_server_ip(self, server):
652 """Get the server fixed or floating IP.
653
654 Based on the configuration we're in, return a correct ip
655 address for validating that a guest is up.
656 """
Alexander Gubanovc8829f82015-11-12 10:35:13 +0200657 if CONF.validation.connect_method == 'floating':
Sean Dague20e98612016-01-06 14:33:28 -0500658 # The tests calling this method don't have a floating IP
zhufl0892cb22016-05-06 14:46:00 +0800659 # and can't make use of the validation resources. So the
Sean Dague20e98612016-01-06 14:33:28 -0500660 # method is creating the floating IP there.
661 return self.create_floating_ip(server)['ip']
662 elif CONF.validation.connect_method == 'fixed':
663 addresses = server['addresses'][CONF.validation.network_for_ssh]
664 for address in addresses:
665 if address['version'] == CONF.validation.ip_version_for_ssh:
666 return address['addr']
667 raise exceptions.ServerUnreachable()
Alexander Gubanovc8829f82015-11-12 10:35:13 +0200668 else:
Sean Dague20e98612016-01-06 14:33:28 -0500669 raise exceptions.InvalidConfiguration()
Alexander Gubanovc8829f82015-11-12 10:35:13 +0200670
Andrea Frittoli2e733b52014-07-16 14:12:11 +0100671
Andrea Frittoli4971fc82014-09-25 10:22:20 +0100672class NetworkScenarioTest(ScenarioTest):
Yair Fried1fc32a12014-08-04 09:11:30 +0300673 """Base class for network scenario tests.
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000674
Yair Fried1fc32a12014-08-04 09:11:30 +0300675 This class provide helpers for network scenario tests, using the neutron
676 API. Helpers from ancestor which use the nova network API are overridden
677 with the neutron API.
678
679 This Class also enforces using Neutron instead of novanetwork.
680 Subclassed tests will be skipped if Neutron is not enabled
681
682 """
683
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000684 credentials = ['primary', 'admin']
685
Yair Fried1fc32a12014-08-04 09:11:30 +0300686 @classmethod
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +0000687 def skip_checks(cls):
688 super(NetworkScenarioTest, cls).skip_checks()
Andrea Frittoli2ddc2632014-09-25 11:03:00 +0100689 if not CONF.service_available.neutron:
690 raise cls.skipException('Neutron not available')
Yair Fried1fc32a12014-08-04 09:11:30 +0300691
692 @classmethod
Andrea Frittoliac20b5e2014-09-15 13:31:14 +0100693 def resource_setup(cls):
694 super(NetworkScenarioTest, cls).resource_setup()
Yair Fried1fc32a12014-08-04 09:11:30 +0300695 cls.tenant_id = cls.manager.identity_client.tenant_id
Yair Fried1fc32a12014-08-04 09:11:30 +0300696
Ken'ichi Ohmichi43e7fcf2016-04-04 11:59:13 -0700697 def _create_network(self, networks_client=None,
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000698 routers_client=None, tenant_id=None,
Markus Zoeller156b5da2016-07-11 18:10:31 +0200699 namestart='network-smoke-',
700 port_security_enabled=True):
John Warren94d8faf2015-09-15 12:22:24 -0400701 if not networks_client:
702 networks_client = self.networks_client
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000703 if not routers_client:
704 routers_client = self.routers_client
Yair Frieddb6c9e92014-08-06 08:53:13 +0300705 if not tenant_id:
Ken'ichi Ohmichi43e7fcf2016-04-04 11:59:13 -0700706 tenant_id = networks_client.tenant_id
Yair Fried1fc32a12014-08-04 09:11:30 +0300707 name = data_utils.rand_name(namestart)
Markus Zoeller156b5da2016-07-11 18:10:31 +0200708 network_kwargs = dict(name=name, tenant_id=tenant_id,
709 port_security_enabled=port_security_enabled)
710 result = networks_client.create_network(**network_kwargs)
Steve Heyman33735f22016-05-24 09:28:08 -0500711 network = result['network']
712
713 self.assertEqual(network['name'], name)
Jordan Pittier9e227c52016-02-09 14:35:18 +0100714 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
Steve Heyman33735f22016-05-24 09:28:08 -0500715 self.networks_client.delete_network,
716 network['id'])
Yair Fried1fc32a12014-08-04 09:11:30 +0300717 return network
718
719 def _list_networks(self, *args, **kwargs):
720 """List networks using admin creds """
John Warren94d8faf2015-09-15 12:22:24 -0400721 networks_list = self.admin_manager.networks_client.list_networks(
ghanshyam2f7cc022015-06-26 18:18:11 +0900722 *args, **kwargs)
723 return networks_list['networks']
Yair Fried1fc32a12014-08-04 09:11:30 +0300724
725 def _list_subnets(self, *args, **kwargs):
726 """List subnets using admin creds """
John Warren3961acd2015-10-02 14:38:53 -0400727 subnets_list = self.admin_manager.subnets_client.list_subnets(
ghanshyam2f7cc022015-06-26 18:18:11 +0900728 *args, **kwargs)
729 return subnets_list['subnets']
Yair Fried1fc32a12014-08-04 09:11:30 +0300730
731 def _list_routers(self, *args, **kwargs):
732 """List routers using admin creds """
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000733 routers_list = self.admin_manager.routers_client.list_routers(
ghanshyam2f7cc022015-06-26 18:18:11 +0900734 *args, **kwargs)
735 return routers_list['routers']
Yair Fried1fc32a12014-08-04 09:11:30 +0300736
737 def _list_ports(self, *args, **kwargs):
738 """List ports using admin creds """
John Warren49c0fe52015-10-22 12:35:54 -0400739 ports_list = self.admin_manager.ports_client.list_ports(
ghanshyam2f7cc022015-06-26 18:18:11 +0900740 *args, **kwargs)
741 return ports_list['ports']
Yair Fried1fc32a12014-08-04 09:11:30 +0300742
Yair Fried564d89d2015-08-06 17:02:12 +0300743 def _list_agents(self, *args, **kwargs):
744 """List agents using admin creds """
Ken'ichi Ohmichi71860062015-12-15 08:20:13 +0000745 agents_list = self.admin_manager.network_agents_client.list_agents(
Yair Fried564d89d2015-08-06 17:02:12 +0300746 *args, **kwargs)
747 return agents_list['agents']
748
Ken'ichi Ohmichi43e7fcf2016-04-04 11:59:13 -0700749 def _create_subnet(self, network, subnets_client=None,
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000750 routers_client=None, namestart='subnet-smoke',
751 **kwargs):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000752 """Create a subnet for the given network
753
754 within the cidr block configured for tenant networks.
Yair Fried1fc32a12014-08-04 09:11:30 +0300755 """
John Warren3961acd2015-10-02 14:38:53 -0400756 if not subnets_client:
757 subnets_client = self.subnets_client
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000758 if not routers_client:
759 routers_client = self.routers_client
Yair Fried1fc32a12014-08-04 09:11:30 +0300760
761 def cidr_in_use(cidr, tenant_id):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000762 """Check cidr existence
763
lei zhangdd552b22015-11-25 20:41:48 +0800764 :returns: True if subnet with cidr already exist in tenant
765 False else
Yair Fried1fc32a12014-08-04 09:11:30 +0300766 """
767 cidr_in_use = self._list_subnets(tenant_id=tenant_id, cidr=cidr)
768 return len(cidr_in_use) != 0
769
Kirill Shileev14113572014-11-21 16:58:02 +0300770 ip_version = kwargs.pop('ip_version', 4)
771
772 if ip_version == 6:
773 tenant_cidr = netaddr.IPNetwork(
Sean Dagueed6e5862016-04-04 10:49:13 -0400774 CONF.network.project_network_v6_cidr)
775 num_bits = CONF.network.project_network_v6_mask_bits
Kirill Shileev14113572014-11-21 16:58:02 +0300776 else:
Sean Dagueed6e5862016-04-04 10:49:13 -0400777 tenant_cidr = netaddr.IPNetwork(CONF.network.project_network_cidr)
778 num_bits = CONF.network.project_network_mask_bits
Kirill Shileev14113572014-11-21 16:58:02 +0300779
Yair Fried1fc32a12014-08-04 09:11:30 +0300780 result = None
Kirill Shileev14113572014-11-21 16:58:02 +0300781 str_cidr = None
Yair Fried1fc32a12014-08-04 09:11:30 +0300782 # Repeatedly attempt subnet creation with sequential cidr
783 # blocks until an unallocated block is found.
Kirill Shileev14113572014-11-21 16:58:02 +0300784 for subnet_cidr in tenant_cidr.subnet(num_bits):
Yair Fried1fc32a12014-08-04 09:11:30 +0300785 str_cidr = str(subnet_cidr)
Steve Heyman33735f22016-05-24 09:28:08 -0500786 if cidr_in_use(str_cidr, tenant_id=network['tenant_id']):
Yair Fried1fc32a12014-08-04 09:11:30 +0300787 continue
788
789 subnet = dict(
790 name=data_utils.rand_name(namestart),
Steve Heyman33735f22016-05-24 09:28:08 -0500791 network_id=network['id'],
792 tenant_id=network['tenant_id'],
Yair Fried1fc32a12014-08-04 09:11:30 +0300793 cidr=str_cidr,
Kirill Shileev14113572014-11-21 16:58:02 +0300794 ip_version=ip_version,
Yair Fried1fc32a12014-08-04 09:11:30 +0300795 **kwargs
796 )
797 try:
John Warren3961acd2015-10-02 14:38:53 -0400798 result = subnets_client.create_subnet(**subnet)
Yair Fried1fc32a12014-08-04 09:11:30 +0300799 break
Masayuki Igawad9388762015-01-20 14:56:42 +0900800 except lib_exc.Conflict as e:
Yair Fried1fc32a12014-08-04 09:11:30 +0300801 is_overlapping_cidr = 'overlaps with another subnet' in str(e)
802 if not is_overlapping_cidr:
803 raise
804 self.assertIsNotNone(result, 'Unable to allocate tenant network')
Steve Heyman33735f22016-05-24 09:28:08 -0500805
806 subnet = result['subnet']
807 self.assertEqual(subnet['cidr'], str_cidr)
808
809 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
810 subnets_client.delete_subnet, subnet['id'])
811
Yair Fried1fc32a12014-08-04 09:11:30 +0300812 return subnet
813
Itzik Brown2ca01cd2014-12-08 12:58:20 +0200814 def _create_port(self, network_id, client=None, namestart='port-quotatest',
815 **kwargs):
Yair Frieddb6c9e92014-08-06 08:53:13 +0300816 if not client:
John Warren49c0fe52015-10-22 12:35:54 -0400817 client = self.ports_client
Yair Fried1fc32a12014-08-04 09:11:30 +0300818 name = data_utils.rand_name(namestart)
David Kranz34e88122014-12-11 15:24:05 -0500819 result = client.create_port(
Yair Fried1fc32a12014-08-04 09:11:30 +0300820 name=name,
Itzik Brown2ca01cd2014-12-08 12:58:20 +0200821 network_id=network_id,
822 **kwargs)
Yair Fried1fc32a12014-08-04 09:11:30 +0300823 self.assertIsNotNone(result, 'Unable to allocate port')
Steve Heyman33735f22016-05-24 09:28:08 -0500824 port = result['port']
825 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
826 client.delete_port, port['id'])
Yair Fried1fc32a12014-08-04 09:11:30 +0300827 return port
828
Kirill Shileev14113572014-11-21 16:58:02 +0300829 def _get_server_port_id_and_ip4(self, server, ip_addr=None):
Kevin Benton1d0c1dc2016-02-04 14:30:08 -0800830 ports = self._list_ports(device_id=server['id'], fixed_ip=ip_addr)
Sean M. Collins2e896832015-12-15 13:58:47 -0500831 # A port can have more then one IP address in some cases.
832 # If the network is dual-stack (IPv4 + IPv6), this port is associated
833 # with 2 subnets
Vasyl Saienko8fd517c2016-05-30 09:52:54 +0300834 p_status = ['ACTIVE']
835 # NOTE(vsaienko) With Ironic, instances live on separate hardware
836 # servers. Neutron does not bind ports for Ironic instances, as a
837 # result the port remains in the DOWN state.
838 if CONF.service_available.ironic:
839 p_status.append('DOWN')
Daniel Mellado9e3e1062015-08-06 18:07:05 +0200840 port_map = [(p["id"], fxip["ip_address"])
841 for p in ports
842 for fxip in p["fixed_ips"]
Yatin Kumbhareee4924c2016-06-09 15:12:06 +0530843 if netutils.is_valid_ipv4(fxip["ip_address"])
Vasyl Saienko8fd517c2016-05-30 09:52:54 +0300844 and p['status'] in p_status]
Kevin Benton1d0c1dc2016-02-04 14:30:08 -0800845 inactive = [p for p in ports if p['status'] != 'ACTIVE']
846 if inactive:
847 LOG.warning("Instance has ports that are not ACTIVE: %s", inactive)
Daniel Mellado9e3e1062015-08-06 18:07:05 +0200848
John L. Villalovosb83286f2015-11-04 14:46:57 -0800849 self.assertNotEqual(0, len(port_map),
850 "No IPv4 addresses found in: %s" % ports)
Daniel Mellado9e3e1062015-08-06 18:07:05 +0200851 self.assertEqual(len(port_map), 1,
852 "Found multiple IPv4 addresses: %s. "
853 "Unable to determine which port to target."
854 % port_map)
855 return port_map[0]
Yair Fried1fc32a12014-08-04 09:11:30 +0300856
David Shrewsbury9bac3662014-08-07 15:07:01 -0400857 def _get_network_by_name(self, network_name):
858 net = self._list_networks(name=network_name)
Adam Gandelman878a5fd2015-03-30 14:33:36 -0700859 self.assertNotEqual(len(net), 0,
860 "Unable to get network by name: %s" % network_name)
Steve Heyman33735f22016-05-24 09:28:08 -0500861 return net[0]
David Shrewsbury9bac3662014-08-07 15:07:01 -0400862
Yair Friedae0e73d2014-11-24 11:56:26 +0200863 def create_floating_ip(self, thing, external_network_id=None,
864 port_id=None, client=None):
Ken'ichi Ohmichia112a592015-11-17 08:49:37 +0000865 """Create a floating IP and associates to a resource/port on Neutron"""
Yair Friedae0e73d2014-11-24 11:56:26 +0200866 if not external_network_id:
867 external_network_id = CONF.network.public_network_id
Yair Frieddb6c9e92014-08-06 08:53:13 +0300868 if not client:
John Warrenfbf2a892015-11-17 12:36:14 -0500869 client = self.floating_ips_client
Yair Fried1fc32a12014-08-04 09:11:30 +0300870 if not port_id:
Kirill Shileev14113572014-11-21 16:58:02 +0300871 port_id, ip4 = self._get_server_port_id_and_ip4(thing)
872 else:
873 ip4 = None
David Kranz34e88122014-12-11 15:24:05 -0500874 result = client.create_floatingip(
Yair Fried1fc32a12014-08-04 09:11:30 +0300875 floating_network_id=external_network_id,
876 port_id=port_id,
Kirill Shileev14113572014-11-21 16:58:02 +0300877 tenant_id=thing['tenant_id'],
878 fixed_ip_address=ip4
Yair Fried1fc32a12014-08-04 09:11:30 +0300879 )
Steve Heyman33735f22016-05-24 09:28:08 -0500880 floating_ip = result['floatingip']
Jordan Pittier9e227c52016-02-09 14:35:18 +0100881 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
Steve Heyman33735f22016-05-24 09:28:08 -0500882 self.floating_ips_client.delete_floatingip,
883 floating_ip['id'])
Yair Fried1fc32a12014-08-04 09:11:30 +0300884 return floating_ip
885
886 def _associate_floating_ip(self, floating_ip, server):
Kirill Shileev14113572014-11-21 16:58:02 +0300887 port_id, _ = self._get_server_port_id_and_ip4(server)
Steve Heyman33735f22016-05-24 09:28:08 -0500888 kwargs = dict(port_id=port_id)
889 floating_ip = self.floating_ips_client.update_floatingip(
890 floating_ip['id'], **kwargs)['floatingip']
891 self.assertEqual(port_id, floating_ip['port_id'])
Yair Fried1fc32a12014-08-04 09:11:30 +0300892 return floating_ip
893
894 def _disassociate_floating_ip(self, floating_ip):
Steve Heyman33735f22016-05-24 09:28:08 -0500895 """:param floating_ip: floating_ips_client.create_floatingip"""
896 kwargs = dict(port_id=None)
897 floating_ip = self.floating_ips_client.update_floatingip(
898 floating_ip['id'], **kwargs)['floatingip']
899 self.assertIsNone(floating_ip['port_id'])
Yair Fried1fc32a12014-08-04 09:11:30 +0300900 return floating_ip
901
Yair Fried45f92952014-06-26 05:19:19 +0300902 def check_floating_ip_status(self, floating_ip, status):
Carl Baldwina754e2d2014-10-23 22:47:41 +0000903 """Verifies floatingip reaches the given status
Yair Fried45f92952014-06-26 05:19:19 +0300904
Steve Heyman33735f22016-05-24 09:28:08 -0500905 :param dict floating_ip: floating IP dict to check status
Yair Fried45f92952014-06-26 05:19:19 +0300906 :param status: target status
907 :raises: AssertionError if status doesn't match
908 """
Steve Heyman33735f22016-05-24 09:28:08 -0500909 floatingip_id = floating_ip['id']
910
Carl Baldwina754e2d2014-10-23 22:47:41 +0000911 def refresh():
Steve Heyman33735f22016-05-24 09:28:08 -0500912 result = (self.floating_ips_client.
913 show_floatingip(floatingip_id)['floatingip'])
914 return status == result['status']
Carl Baldwina754e2d2014-10-23 22:47:41 +0000915
916 tempest.test.call_until_true(refresh,
917 CONF.network.build_timeout,
918 CONF.network.build_interval)
Steve Heyman33735f22016-05-24 09:28:08 -0500919 floating_ip = self.floating_ips_client.show_floatingip(
920 floatingip_id)['floatingip']
921 self.assertEqual(status, floating_ip['status'],
Yair Fried45f92952014-06-26 05:19:19 +0300922 message="FloatingIP: {fp} is at status: {cst}. "
923 "failed to reach status: {st}"
Steve Heyman33735f22016-05-24 09:28:08 -0500924 .format(fp=floating_ip, cst=floating_ip['status'],
Yair Fried45f92952014-06-26 05:19:19 +0300925 st=status))
926 LOG.info("FloatingIP: {fp} is at status: {st}"
927 .format(fp=floating_ip, st=status))
928
Yair Fried1fc32a12014-08-04 09:11:30 +0300929 def _check_tenant_network_connectivity(self, server,
930 username,
931 private_key,
932 should_connect=True,
933 servers_for_debug=None):
Sean Dagueed6e5862016-04-04 10:49:13 -0400934 if not CONF.network.project_networks_reachable:
Yair Fried1fc32a12014-08-04 09:11:30 +0300935 msg = 'Tenant networks not configured to be reachable.'
936 LOG.info(msg)
937 return
938 # The target login is assumed to have been configured for
939 # key-based authentication by cloud-init.
940 try:
Matthew Treinish71426682015-04-23 11:19:38 -0400941 for net_name, ip_addresses in six.iteritems(server['addresses']):
Yair Fried1fc32a12014-08-04 09:11:30 +0300942 for ip_address in ip_addresses:
ghanshyam807211c2014-12-18 13:21:22 +0900943 self.check_vm_connectivity(ip_address['addr'],
Yair Friedae0e73d2014-11-24 11:56:26 +0200944 username,
945 private_key,
946 should_connect=should_connect)
Yair Fried1fc32a12014-08-04 09:11:30 +0300947 except Exception as e:
948 LOG.exception('Tenant network connectivity check failed')
949 self._log_console_output(servers_for_debug)
Ken'ichi Ohmichi6e201f52014-10-01 04:21:39 +0000950 self._log_net_info(e)
Yair Fried1fc32a12014-08-04 09:11:30 +0300951 raise
952
Yair Friedbc46f592015-11-18 16:29:34 +0200953 def _check_remote_connectivity(self, source, dest, should_succeed=True,
954 nic=None):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +0000955 """check ping server via source ssh connection
Yair Fried1fc32a12014-08-04 09:11:30 +0300956
957 :param source: RemoteClient: an ssh connection from which to ping
958 :param dest: and IP to ping against
959 :param should_succeed: boolean should ping succeed or not
Yair Friedbc46f592015-11-18 16:29:34 +0200960 :param nic: specific network interface to ping from
Yair Fried1fc32a12014-08-04 09:11:30 +0300961 :returns: boolean -- should_succeed == ping
962 :returns: ping is false if ping failed
963 """
964 def ping_remote():
965 try:
Yair Friedbc46f592015-11-18 16:29:34 +0200966 source.ping_host(dest, nic=nic)
Andrey Pavlov64723762015-04-29 06:24:58 +0300967 except lib_exc.SSHExecCommandFailed:
zhangguoqing6c096642016-01-04 06:17:21 +0000968 LOG.warning('Failed to ping IP: %s via a ssh connection '
969 'from: %s.' % (dest, source.ssh_client.host))
Yair Fried1fc32a12014-08-04 09:11:30 +0300970 return not should_succeed
971 return should_succeed
972
973 return tempest.test.call_until_true(ping_remote,
lanoux5fc14522015-09-21 08:17:35 +0000974 CONF.validation.ping_timeout,
Yair Fried1fc32a12014-08-04 09:11:30 +0300975 1)
976
John Warren456d9ae2016-01-12 15:36:33 -0500977 def _create_security_group(self, security_group_rules_client=None,
978 tenant_id=None,
John Warrenf9606e92015-12-10 12:12:42 -0500979 namestart='secgroup-smoke',
980 security_groups_client=None):
John Warren456d9ae2016-01-12 15:36:33 -0500981 if security_group_rules_client is None:
982 security_group_rules_client = self.security_group_rules_client
John Warrenf9606e92015-12-10 12:12:42 -0500983 if security_groups_client is None:
984 security_groups_client = self.security_groups_client
Yair Frieddb6c9e92014-08-06 08:53:13 +0300985 if tenant_id is None:
John Warrenf9606e92015-12-10 12:12:42 -0500986 tenant_id = security_groups_client.tenant_id
987 secgroup = self._create_empty_security_group(
988 namestart=namestart, client=security_groups_client,
989 tenant_id=tenant_id)
Yair Fried1fc32a12014-08-04 09:11:30 +0300990
991 # Add rules to the security group
John Warrenf9606e92015-12-10 12:12:42 -0500992 rules = self._create_loginable_secgroup_rule(
John Warren456d9ae2016-01-12 15:36:33 -0500993 security_group_rules_client=security_group_rules_client,
994 secgroup=secgroup,
John Warrenf9606e92015-12-10 12:12:42 -0500995 security_groups_client=security_groups_client)
Yair Fried1fc32a12014-08-04 09:11:30 +0300996 for rule in rules:
Steve Heyman33735f22016-05-24 09:28:08 -0500997 self.assertEqual(tenant_id, rule['tenant_id'])
998 self.assertEqual(secgroup['id'], rule['security_group_id'])
Yair Fried1fc32a12014-08-04 09:11:30 +0300999 return secgroup
1000
Yair Frieddb6c9e92014-08-06 08:53:13 +03001001 def _create_empty_security_group(self, client=None, tenant_id=None,
Yair Fried1fc32a12014-08-04 09:11:30 +03001002 namestart='secgroup-smoke'):
1003 """Create a security group without rules.
1004
1005 Default rules will be created:
1006 - IPv4 egress to any
1007 - IPv6 egress to any
1008
1009 :param tenant_id: secgroup will be created in this tenant
Steve Heyman33735f22016-05-24 09:28:08 -05001010 :returns: the created security group
Yair Fried1fc32a12014-08-04 09:11:30 +03001011 """
1012 if client is None:
John Warrenf9606e92015-12-10 12:12:42 -05001013 client = self.security_groups_client
Yair Frieddb6c9e92014-08-06 08:53:13 +03001014 if not tenant_id:
Ken'ichi Ohmichi88f12c12014-12-24 01:02:58 +00001015 tenant_id = client.tenant_id
Yair Fried1fc32a12014-08-04 09:11:30 +03001016 sg_name = data_utils.rand_name(namestart)
1017 sg_desc = sg_name + " description"
1018 sg_dict = dict(name=sg_name,
1019 description=sg_desc)
1020 sg_dict['tenant_id'] = tenant_id
David Kranz34e88122014-12-11 15:24:05 -05001021 result = client.create_security_group(**sg_dict)
Steve Heyman33735f22016-05-24 09:28:08 -05001022
1023 secgroup = result['security_group']
1024 self.assertEqual(secgroup['name'], sg_name)
1025 self.assertEqual(tenant_id, secgroup['tenant_id'])
1026 self.assertEqual(secgroup['description'], sg_desc)
1027
Jordan Pittier9e227c52016-02-09 14:35:18 +01001028 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
Steve Heyman33735f22016-05-24 09:28:08 -05001029 client.delete_security_group, secgroup['id'])
Yair Fried1fc32a12014-08-04 09:11:30 +03001030 return secgroup
1031
Yair Frieddb6c9e92014-08-06 08:53:13 +03001032 def _default_security_group(self, client=None, tenant_id=None):
Yair Fried1fc32a12014-08-04 09:11:30 +03001033 """Get default secgroup for given tenant_id.
1034
1035 :returns: DeletableSecurityGroup -- default secgroup for given tenant
1036 """
1037 if client is None:
John Warrenf9606e92015-12-10 12:12:42 -05001038 client = self.security_groups_client
Yair Frieddb6c9e92014-08-06 08:53:13 +03001039 if not tenant_id:
Ken'ichi Ohmichi88f12c12014-12-24 01:02:58 +00001040 tenant_id = client.tenant_id
Yair Fried1fc32a12014-08-04 09:11:30 +03001041 sgs = [
Jordan Pittier8ad86172016-04-25 16:20:53 +02001042 sg for sg in list(client.list_security_groups().values())[0]
Yair Fried1fc32a12014-08-04 09:11:30 +03001043 if sg['tenant_id'] == tenant_id and sg['name'] == 'default'
1044 ]
1045 msg = "No default security group for tenant %s." % (tenant_id)
1046 self.assertTrue(len(sgs) > 0, msg)
Steve Heyman33735f22016-05-24 09:28:08 -05001047 return sgs[0]
Yair Fried1fc32a12014-08-04 09:11:30 +03001048
John Warren456d9ae2016-01-12 15:36:33 -05001049 def _create_security_group_rule(self, secgroup=None,
1050 sec_group_rules_client=None,
John Warrenf9606e92015-12-10 12:12:42 -05001051 tenant_id=None,
1052 security_groups_client=None, **kwargs):
Yair Fried1fc32a12014-08-04 09:11:30 +03001053 """Create a rule from a dictionary of rule parameters.
1054
1055 Create a rule in a secgroup. if secgroup not defined will search for
1056 default secgroup in tenant_id.
1057
Steve Heyman33735f22016-05-24 09:28:08 -05001058 :param secgroup: the security group.
Yair Fried1fc32a12014-08-04 09:11:30 +03001059 :param tenant_id: if secgroup not passed -- the tenant in which to
1060 search for default secgroup
1061 :param kwargs: a dictionary containing rule parameters:
1062 for example, to allow incoming ssh:
1063 rule = {
1064 direction: 'ingress'
1065 protocol:'tcp',
1066 port_range_min: 22,
1067 port_range_max: 22
1068 }
1069 """
John Warren456d9ae2016-01-12 15:36:33 -05001070 if sec_group_rules_client is None:
1071 sec_group_rules_client = self.security_group_rules_client
John Warrenf9606e92015-12-10 12:12:42 -05001072 if security_groups_client is None:
1073 security_groups_client = self.security_groups_client
Yair Frieddb6c9e92014-08-06 08:53:13 +03001074 if not tenant_id:
John Warrenf9606e92015-12-10 12:12:42 -05001075 tenant_id = security_groups_client.tenant_id
Yair Fried1fc32a12014-08-04 09:11:30 +03001076 if secgroup is None:
John Warrenf9606e92015-12-10 12:12:42 -05001077 secgroup = self._default_security_group(
1078 client=security_groups_client, tenant_id=tenant_id)
Yair Fried1fc32a12014-08-04 09:11:30 +03001079
Steve Heyman33735f22016-05-24 09:28:08 -05001080 ruleset = dict(security_group_id=secgroup['id'],
1081 tenant_id=secgroup['tenant_id'])
Yair Fried1fc32a12014-08-04 09:11:30 +03001082 ruleset.update(kwargs)
1083
John Warren456d9ae2016-01-12 15:36:33 -05001084 sg_rule = sec_group_rules_client.create_security_group_rule(**ruleset)
Steve Heyman33735f22016-05-24 09:28:08 -05001085 sg_rule = sg_rule['security_group_rule']
1086
1087 self.assertEqual(secgroup['tenant_id'], sg_rule['tenant_id'])
1088 self.assertEqual(secgroup['id'], sg_rule['security_group_id'])
Yair Fried1fc32a12014-08-04 09:11:30 +03001089
1090 return sg_rule
1091
John Warren456d9ae2016-01-12 15:36:33 -05001092 def _create_loginable_secgroup_rule(self, security_group_rules_client=None,
1093 secgroup=None,
John Warrenf9606e92015-12-10 12:12:42 -05001094 security_groups_client=None):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +00001095 """Create loginable security group rule
1096
Alex Stafeyevdd5dde92016-05-08 14:35:04 +03001097 This function will create:
1098 1. egress and ingress tcp port 22 allow rule in order to allow ssh
1099 access for ipv4.
1100 2. egress and ingress ipv6 icmp allow rule, in order to allow icmpv6.
1101 3. egress and ingress ipv4 icmp allow rule, in order to allow icmpv4.
Yair Fried1fc32a12014-08-04 09:11:30 +03001102 """
1103
John Warren456d9ae2016-01-12 15:36:33 -05001104 if security_group_rules_client is None:
1105 security_group_rules_client = self.security_group_rules_client
John Warrenf9606e92015-12-10 12:12:42 -05001106 if security_groups_client is None:
1107 security_groups_client = self.security_groups_client
Yair Fried1fc32a12014-08-04 09:11:30 +03001108 rules = []
1109 rulesets = [
1110 dict(
1111 # ssh
1112 protocol='tcp',
1113 port_range_min=22,
1114 port_range_max=22,
1115 ),
1116 dict(
1117 # ping
1118 protocol='icmp',
Andreas Scheuring887ca8e2015-02-03 17:56:12 +01001119 ),
1120 dict(
1121 # ipv6-icmp for ping6
1122 protocol='icmp',
1123 ethertype='IPv6',
Yair Fried1fc32a12014-08-04 09:11:30 +03001124 )
1125 ]
John Warren456d9ae2016-01-12 15:36:33 -05001126 sec_group_rules_client = security_group_rules_client
Yair Fried1fc32a12014-08-04 09:11:30 +03001127 for ruleset in rulesets:
1128 for r_direction in ['ingress', 'egress']:
1129 ruleset['direction'] = r_direction
1130 try:
1131 sg_rule = self._create_security_group_rule(
John Warren456d9ae2016-01-12 15:36:33 -05001132 sec_group_rules_client=sec_group_rules_client,
1133 secgroup=secgroup,
John Warrenf9606e92015-12-10 12:12:42 -05001134 security_groups_client=security_groups_client,
1135 **ruleset)
Masayuki Igawad9388762015-01-20 14:56:42 +09001136 except lib_exc.Conflict as ex:
Yair Fried1fc32a12014-08-04 09:11:30 +03001137 # if rule already exist - skip rule and continue
1138 msg = 'Security group rule already exists'
1139 if msg not in ex._error_string:
1140 raise ex
1141 else:
Steve Heyman33735f22016-05-24 09:28:08 -05001142 self.assertEqual(r_direction, sg_rule['direction'])
Yair Fried1fc32a12014-08-04 09:11:30 +03001143 rules.append(sg_rule)
1144
1145 return rules
1146
Yair Frieddb6c9e92014-08-06 08:53:13 +03001147 def _get_router(self, client=None, tenant_id=None):
Yair Fried1fc32a12014-08-04 09:11:30 +03001148 """Retrieve a router for the given tenant id.
1149
1150 If a public router has been configured, it will be returned.
1151
1152 If a public router has not been configured, but a public
1153 network has, a tenant router will be created and returned that
1154 routes traffic to the public network.
1155 """
Yair Frieddb6c9e92014-08-06 08:53:13 +03001156 if not client:
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +00001157 client = self.routers_client
Yair Frieddb6c9e92014-08-06 08:53:13 +03001158 if not tenant_id:
Ken'ichi Ohmichi88f12c12014-12-24 01:02:58 +00001159 tenant_id = client.tenant_id
Yair Fried1fc32a12014-08-04 09:11:30 +03001160 router_id = CONF.network.public_router_id
1161 network_id = CONF.network.public_network_id
1162 if router_id:
David Kranzca4c7e72015-05-27 11:39:19 -04001163 body = client.show_router(router_id)
Steve Heyman33735f22016-05-24 09:28:08 -05001164 return body['router']
Yair Fried1fc32a12014-08-04 09:11:30 +03001165 elif network_id:
Yair Frieddb6c9e92014-08-06 08:53:13 +03001166 router = self._create_router(client, tenant_id)
Steve Heyman33735f22016-05-24 09:28:08 -05001167 kwargs = {'external_gateway_info': dict(network_id=network_id)}
1168 router = client.update_router(router['id'], **kwargs)['router']
Yair Fried1fc32a12014-08-04 09:11:30 +03001169 return router
1170 else:
1171 raise Exception("Neither of 'public_router_id' or "
1172 "'public_network_id' has been defined.")
1173
Yair Frieddb6c9e92014-08-06 08:53:13 +03001174 def _create_router(self, client=None, tenant_id=None,
1175 namestart='router-smoke'):
1176 if not client:
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +00001177 client = self.routers_client
Yair Frieddb6c9e92014-08-06 08:53:13 +03001178 if not tenant_id:
Ken'ichi Ohmichi88f12c12014-12-24 01:02:58 +00001179 tenant_id = client.tenant_id
Yair Fried1fc32a12014-08-04 09:11:30 +03001180 name = data_utils.rand_name(namestart)
David Kranz34e88122014-12-11 15:24:05 -05001181 result = client.create_router(name=name,
1182 admin_state_up=True,
1183 tenant_id=tenant_id)
Steve Heyman33735f22016-05-24 09:28:08 -05001184 router = result['router']
1185 self.assertEqual(router['name'], name)
1186 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
1187 client.delete_router,
1188 router['id'])
Yair Fried1fc32a12014-08-04 09:11:30 +03001189 return router
1190
Alok Maurya6384bbb2014-07-13 06:44:29 -07001191 def _update_router_admin_state(self, router, admin_state_up):
Steve Heyman33735f22016-05-24 09:28:08 -05001192 kwargs = dict(admin_state_up=admin_state_up)
1193 router = self.routers_client.update_router(
1194 router['id'], **kwargs)['router']
1195 self.assertEqual(admin_state_up, router['admin_state_up'])
Alok Maurya6384bbb2014-07-13 06:44:29 -07001196
Ken'ichi Ohmichi43e7fcf2016-04-04 11:59:13 -07001197 def create_networks(self, networks_client=None,
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +00001198 routers_client=None, subnets_client=None,
Markus Zoeller156b5da2016-07-11 18:10:31 +02001199 tenant_id=None, dns_nameservers=None,
1200 port_security_enabled=True):
Yair Fried1fc32a12014-08-04 09:11:30 +03001201 """Create a network with a subnet connected to a router.
1202
David Shrewsbury9bac3662014-08-07 15:07:01 -04001203 The baremetal driver is a special case since all nodes are
1204 on the same shared network.
1205
Yair Fried413bf2d2014-11-19 17:07:11 +02001206 :param tenant_id: id of tenant to create resources in.
1207 :param dns_nameservers: list of dns servers to send to subnet.
Yair Fried1fc32a12014-08-04 09:11:30 +03001208 :returns: network, subnet, router
1209 """
David Shrewsbury9bac3662014-08-07 15:07:01 -04001210 if CONF.baremetal.driver_enabled:
1211 # NOTE(Shrews): This exception is for environments where tenant
1212 # credential isolation is available, but network separation is
1213 # not (the current baremetal case). Likely can be removed when
1214 # test account mgmt is reworked:
1215 # https://blueprints.launchpad.net/tempest/+spec/test-accounts
Adam Gandelman878a5fd2015-03-30 14:33:36 -07001216 if not CONF.compute.fixed_network_name:
1217 m = 'fixed_network_name must be specified in config'
1218 raise exceptions.InvalidConfiguration(m)
David Shrewsbury9bac3662014-08-07 15:07:01 -04001219 network = self._get_network_by_name(
1220 CONF.compute.fixed_network_name)
1221 router = None
1222 subnet = None
1223 else:
John Warren94d8faf2015-09-15 12:22:24 -04001224 network = self._create_network(
Ken'ichi Ohmichi43e7fcf2016-04-04 11:59:13 -07001225 networks_client=networks_client,
Markus Zoeller156b5da2016-07-11 18:10:31 +02001226 tenant_id=tenant_id,
1227 port_security_enabled=port_security_enabled)
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +00001228 router = self._get_router(client=routers_client,
1229 tenant_id=tenant_id)
Ken'ichi Ohmichi43e7fcf2016-04-04 11:59:13 -07001230 subnet_kwargs = dict(network=network,
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +00001231 subnets_client=subnets_client,
1232 routers_client=routers_client)
Yair Fried413bf2d2014-11-19 17:07:11 +02001233 # use explicit check because empty list is a valid option
1234 if dns_nameservers is not None:
1235 subnet_kwargs['dns_nameservers'] = dns_nameservers
1236 subnet = self._create_subnet(**subnet_kwargs)
Steve Heyman33735f22016-05-24 09:28:08 -05001237 if not routers_client:
1238 routers_client = self.routers_client
1239 router_id = router['id']
1240 routers_client.add_router_interface(router_id,
1241 subnet_id=subnet['id'])
1242
1243 # save a cleanup job to remove this association between
1244 # router and subnet
1245 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
1246 routers_client.remove_router_interface, router_id,
1247 subnet_id=subnet['id'])
Yair Fried1fc32a12014-08-04 09:11:30 +03001248 return network, subnet, router
1249
1250
David Shrewsbury06f7f8a2014-05-20 13:55:57 -04001251# power/provision states as of icehouse
1252class BaremetalPowerStates(object):
1253 """Possible power states of an Ironic node."""
1254 POWER_ON = 'power on'
1255 POWER_OFF = 'power off'
1256 REBOOT = 'rebooting'
1257 SUSPEND = 'suspended'
1258
1259
1260class BaremetalProvisionStates(object):
1261 """Possible provision states of an Ironic node."""
1262 NOSTATE = None
1263 INIT = 'initializing'
1264 ACTIVE = 'active'
1265 BUILDING = 'building'
1266 DEPLOYWAIT = 'wait call-back'
1267 DEPLOYING = 'deploying'
1268 DEPLOYFAIL = 'deploy failed'
1269 DEPLOYDONE = 'deploy complete'
1270 DELETING = 'deleting'
1271 DELETED = 'deleted'
1272 ERROR = 'error'
1273
1274
Adam Gandelmanc78c7572014-08-28 18:38:55 -07001275class BaremetalScenarioTest(ScenarioTest):
Andrea Frittolib21de6c2015-02-06 20:12:38 +00001276
1277 credentials = ['primary', 'admin']
1278
Adam Gandelman4a48a602014-03-20 18:23:18 -07001279 @classmethod
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +00001280 def skip_checks(cls):
1281 super(BaremetalScenarioTest, cls).skip_checks()
Adam Gandelman4a48a602014-03-20 18:23:18 -07001282 if (not CONF.service_available.ironic or
1283 not CONF.baremetal.driver_enabled):
1284 msg = 'Ironic not available or Ironic compute driver not enabled'
1285 raise cls.skipException(msg)
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +00001286
1287 @classmethod
Andrea Frittolib21de6c2015-02-06 20:12:38 +00001288 def setup_clients(cls):
1289 super(BaremetalScenarioTest, cls).setup_clients()
Adam Gandelman4a48a602014-03-20 18:23:18 -07001290
Andrea Frittolib21de6c2015-02-06 20:12:38 +00001291 cls.baremetal_client = cls.admin_manager.baremetal_client
Adam Gandelman4a48a602014-03-20 18:23:18 -07001292
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +00001293 @classmethod
1294 def resource_setup(cls):
1295 super(BaremetalScenarioTest, cls).resource_setup()
Adam Gandelman4a48a602014-03-20 18:23:18 -07001296 # allow any issues obtaining the node list to raise early
Adam Gandelmanc78c7572014-08-28 18:38:55 -07001297 cls.baremetal_client.list_nodes()
Adam Gandelman4a48a602014-03-20 18:23:18 -07001298
1299 def _node_state_timeout(self, node_id, state_attr,
1300 target_states, timeout=10, interval=1):
1301 if not isinstance(target_states, list):
1302 target_states = [target_states]
1303
1304 def check_state():
1305 node = self.get_node(node_id=node_id)
Adam Gandelmanc78c7572014-08-28 18:38:55 -07001306 if node.get(state_attr) in target_states:
Adam Gandelman4a48a602014-03-20 18:23:18 -07001307 return True
1308 return False
1309
1310 if not tempest.test.call_until_true(
1311 check_state, timeout, interval):
1312 msg = ("Timed out waiting for node %s to reach %s state(s) %s" %
1313 (node_id, state_attr, target_states))
1314 raise exceptions.TimeoutException(msg)
1315
1316 def wait_provisioning_state(self, node_id, state, timeout):
1317 self._node_state_timeout(
1318 node_id=node_id, state_attr='provision_state',
1319 target_states=state, timeout=timeout)
1320
1321 def wait_power_state(self, node_id, state):
1322 self._node_state_timeout(
1323 node_id=node_id, state_attr='power_state',
1324 target_states=state, timeout=CONF.baremetal.power_timeout)
1325
1326 def wait_node(self, instance_id):
1327 """Waits for a node to be associated with instance_id."""
Zhi Kun Liu4a8d1ea2014-04-15 22:08:21 -05001328
Adam Gandelman4a48a602014-03-20 18:23:18 -07001329 def _get_node():
Jordan Pittier9e227c52016-02-09 14:35:18 +01001330 node = test_utils.call_and_ignore_notfound_exc(
1331 self.get_node, instance_id=instance_id)
Adam Gandelman4a48a602014-03-20 18:23:18 -07001332 return node is not None
1333
1334 if not tempest.test.call_until_true(
1335 _get_node, CONF.baremetal.association_timeout, 1):
1336 msg = ('Timed out waiting to get Ironic node by instance id %s'
1337 % instance_id)
1338 raise exceptions.TimeoutException(msg)
1339
1340 def get_node(self, node_id=None, instance_id=None):
1341 if node_id:
Adam Gandelmanc78c7572014-08-28 18:38:55 -07001342 _, body = self.baremetal_client.show_node(node_id)
1343 return body
Adam Gandelman4a48a602014-03-20 18:23:18 -07001344 elif instance_id:
Adam Gandelmanc78c7572014-08-28 18:38:55 -07001345 _, body = self.baremetal_client.show_node_by_instance_uuid(
1346 instance_id)
1347 if body['nodes']:
1348 return body['nodes'][0]
Adam Gandelman4a48a602014-03-20 18:23:18 -07001349
Adam Gandelmanc78c7572014-08-28 18:38:55 -07001350 def get_ports(self, node_uuid):
Adam Gandelman4a48a602014-03-20 18:23:18 -07001351 ports = []
Adam Gandelmanc78c7572014-08-28 18:38:55 -07001352 _, body = self.baremetal_client.list_node_ports(node_uuid)
1353 for port in body['ports']:
1354 _, p = self.baremetal_client.show_port(port['uuid'])
1355 ports.append(p)
Adam Gandelman4a48a602014-03-20 18:23:18 -07001356 return ports
1357
David Shrewsbury06f7f8a2014-05-20 13:55:57 -04001358 def add_keypair(self):
1359 self.keypair = self.create_keypair()
1360
David Shrewsbury06f7f8a2014-05-20 13:55:57 -04001361 def boot_instance(self):
David Shrewsbury06f7f8a2014-05-20 13:55:57 -04001362 self.instance = self.create_server(
lanoux5fc14522015-09-21 08:17:35 +00001363 key_name=self.keypair['name'])
David Shrewsbury06f7f8a2014-05-20 13:55:57 -04001364
Adam Gandelmanc78c7572014-08-28 18:38:55 -07001365 self.wait_node(self.instance['id'])
1366 self.node = self.get_node(instance_id=self.instance['id'])
David Shrewsbury06f7f8a2014-05-20 13:55:57 -04001367
Adam Gandelmanc78c7572014-08-28 18:38:55 -07001368 self.wait_power_state(self.node['uuid'], BaremetalPowerStates.POWER_ON)
David Shrewsbury06f7f8a2014-05-20 13:55:57 -04001369
1370 self.wait_provisioning_state(
Adam Gandelmanc78c7572014-08-28 18:38:55 -07001371 self.node['uuid'],
David Shrewsbury06f7f8a2014-05-20 13:55:57 -04001372 [BaremetalProvisionStates.DEPLOYWAIT,
1373 BaremetalProvisionStates.ACTIVE],
1374 timeout=15)
1375
Adam Gandelmanc78c7572014-08-28 18:38:55 -07001376 self.wait_provisioning_state(self.node['uuid'],
David Shrewsbury06f7f8a2014-05-20 13:55:57 -04001377 BaremetalProvisionStates.ACTIVE,
1378 timeout=CONF.baremetal.active_timeout)
1379
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +00001380 waiters.wait_for_server_status(self.servers_client,
1381 self.instance['id'], 'ACTIVE')
Adam Gandelmanc78c7572014-08-28 18:38:55 -07001382 self.node = self.get_node(instance_id=self.instance['id'])
ghanshyam0f825252015-08-25 16:02:50 +09001383 self.instance = (self.servers_client.show_server(self.instance['id'])
1384 ['server'])
David Shrewsbury06f7f8a2014-05-20 13:55:57 -04001385
1386 def terminate_instance(self):
Adam Gandelmanc78c7572014-08-28 18:38:55 -07001387 self.servers_client.delete_server(self.instance['id'])
1388 self.wait_power_state(self.node['uuid'],
1389 BaremetalPowerStates.POWER_OFF)
David Shrewsbury06f7f8a2014-05-20 13:55:57 -04001390 self.wait_provisioning_state(
Adam Gandelmanc78c7572014-08-28 18:38:55 -07001391 self.node['uuid'],
David Shrewsbury06f7f8a2014-05-20 13:55:57 -04001392 BaremetalProvisionStates.NOSTATE,
1393 timeout=CONF.baremetal.unprovision_timeout)
1394
Adam Gandelman4a48a602014-03-20 18:23:18 -07001395
Masayuki Igawa1f0ad632014-08-05 13:36:56 +09001396class EncryptionScenarioTest(ScenarioTest):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +00001397 """Base class for encryption scenario tests"""
Kaitlin Farr366a51f2014-04-21 12:43:54 -04001398
Andrea Frittolib21de6c2015-02-06 20:12:38 +00001399 credentials = ['primary', 'admin']
David Kranz4cc852b2015-03-09 14:57:11 -04001400
1401 @classmethod
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +00001402 def setup_clients(cls):
1403 super(EncryptionScenarioTest, cls).setup_clients()
Ivan Kolodyazhnybcfc32e2015-08-06 13:31:36 +03001404 if CONF.volume_feature_enabled.api_v1:
1405 cls.admin_volume_types_client = cls.os_adm.volume_types_client
1406 else:
1407 cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
Kaitlin Farr366a51f2014-04-21 12:43:54 -04001408
Kaitlin Farr366a51f2014-04-21 12:43:54 -04001409 def create_volume_type(self, client=None, name=None):
1410 if not client:
Masayuki Igawa1f0ad632014-08-05 13:36:56 +09001411 client = self.admin_volume_types_client
Kaitlin Farr366a51f2014-04-21 12:43:54 -04001412 if not name:
1413 name = 'generic'
Ken'ichi Ohmichi6ded8df2015-03-23 02:00:19 +00001414 randomized_name = data_utils.rand_name('scenario-type-' + name)
Kaitlin Farr366a51f2014-04-21 12:43:54 -04001415 LOG.debug("Creating a volume type: %s", randomized_name)
Joseph Lanoux6809bab2014-12-18 14:57:18 +00001416 body = client.create_volume_type(
lei zhang83c4bbd2015-11-27 00:35:21 +08001417 name=randomized_name)['volume_type']
Masayuki Igawa1f0ad632014-08-05 13:36:56 +09001418 self.assertIn('id', body)
1419 self.addCleanup(client.delete_volume_type, body['id'])
1420 return body
Kaitlin Farr366a51f2014-04-21 12:43:54 -04001421
1422 def create_encryption_type(self, client=None, type_id=None, provider=None,
1423 key_size=None, cipher=None,
1424 control_location=None):
1425 if not client:
Masayuki Igawa1f0ad632014-08-05 13:36:56 +09001426 client = self.admin_volume_types_client
Kaitlin Farr366a51f2014-04-21 12:43:54 -04001427 if not type_id:
1428 volume_type = self.create_volume_type()
Masayuki Igawa1f0ad632014-08-05 13:36:56 +09001429 type_id = volume_type['id']
Kaitlin Farr366a51f2014-04-21 12:43:54 -04001430 LOG.debug("Creating an encryption type for volume type: %s", type_id)
Masayuki Igawa1f0ad632014-08-05 13:36:56 +09001431 client.create_encryption_type(
1432 type_id, provider=provider, key_size=key_size, cipher=cipher,
John Warrend053ded2015-08-13 15:22:48 +00001433 control_location=control_location)['encryption']
Kaitlin Farr366a51f2014-04-21 12:43:54 -04001434
Kaitlin Farr366a51f2014-04-21 12:43:54 -04001435
Masayuki Igawa0870db52015-09-18 21:08:36 +09001436class ObjectStorageScenarioTest(ScenarioTest):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +00001437 """Provide harness to do Object Storage scenario tests.
Chris Dent0d494112014-08-26 13:48:30 +01001438
1439 Subclasses implement the tests that use the methods provided by this
1440 class.
1441 """
1442
1443 @classmethod
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +00001444 def skip_checks(cls):
Masayuki Igawa0870db52015-09-18 21:08:36 +09001445 super(ObjectStorageScenarioTest, cls).skip_checks()
Chris Dent0d494112014-08-26 13:48:30 +01001446 if not CONF.service_available.swift:
1447 skip_msg = ("%s skipped as swift is not available" %
1448 cls.__name__)
1449 raise cls.skipException(skip_msg)
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +00001450
1451 @classmethod
1452 def setup_credentials(cls):
Masayuki Igawa60ea6c52014-10-15 17:32:14 +09001453 cls.set_network_resources()
Masayuki Igawa0870db52015-09-18 21:08:36 +09001454 super(ObjectStorageScenarioTest, cls).setup_credentials()
Matthew Treinish4a596932015-03-06 20:37:01 -05001455 operator_role = CONF.object_storage.operator_role
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +01001456 cls.os_operator = cls.get_client_manager(roles=[operator_role])
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +00001457
1458 @classmethod
1459 def setup_clients(cls):
Masayuki Igawa0870db52015-09-18 21:08:36 +09001460 super(ObjectStorageScenarioTest, cls).setup_clients()
Chris Dent0d494112014-08-26 13:48:30 +01001461 # Clients for Swift
Matthew Treinish8f268292015-02-24 20:01:36 -05001462 cls.account_client = cls.os_operator.account_client
1463 cls.container_client = cls.os_operator.container_client
1464 cls.object_client = cls.os_operator.object_client
Chris Dent0d494112014-08-26 13:48:30 +01001465
Chris Dentde456a12014-09-10 12:41:15 +01001466 def get_swift_stat(self):
Chris Dent0d494112014-08-26 13:48:30 +01001467 """get swift status for our user account."""
1468 self.account_client.list_account_containers()
1469 LOG.debug('Swift status information obtained successfully')
1470
Chris Dentde456a12014-09-10 12:41:15 +01001471 def create_container(self, container_name=None):
Chris Dent0d494112014-08-26 13:48:30 +01001472 name = container_name or data_utils.rand_name(
1473 'swift-scenario-container')
1474 self.container_client.create_container(name)
1475 # look for the container to assure it is created
Chris Dentde456a12014-09-10 12:41:15 +01001476 self.list_and_check_container_objects(name)
Chris Dent0d494112014-08-26 13:48:30 +01001477 LOG.debug('Container %s created' % (name))
Jordan Pittier9e227c52016-02-09 14:35:18 +01001478 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
Chris Dent1d4313a2014-10-28 12:16:48 +00001479 self.container_client.delete_container,
1480 name)
Chris Dent0d494112014-08-26 13:48:30 +01001481 return name
1482
Chris Dentde456a12014-09-10 12:41:15 +01001483 def delete_container(self, container_name):
Chris Dent0d494112014-08-26 13:48:30 +01001484 self.container_client.delete_container(container_name)
1485 LOG.debug('Container %s deleted' % (container_name))
1486
Chris Dentde456a12014-09-10 12:41:15 +01001487 def upload_object_to_container(self, container_name, obj_name=None):
Chris Dent0d494112014-08-26 13:48:30 +01001488 obj_name = obj_name or data_utils.rand_name('swift-scenario-object')
1489 obj_data = data_utils.arbitrary_string()
1490 self.object_client.create_object(container_name, obj_name, obj_data)
Jordan Pittier9e227c52016-02-09 14:35:18 +01001491 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
Chris Dent1d4313a2014-10-28 12:16:48 +00001492 self.object_client.delete_object,
1493 container_name,
1494 obj_name)
Chris Dent0d494112014-08-26 13:48:30 +01001495 return obj_name, obj_data
1496
Chris Dentde456a12014-09-10 12:41:15 +01001497 def delete_object(self, container_name, filename):
Chris Dent0d494112014-08-26 13:48:30 +01001498 self.object_client.delete_object(container_name, filename)
Chris Dentde456a12014-09-10 12:41:15 +01001499 self.list_and_check_container_objects(container_name,
1500 not_present_obj=[filename])
Chris Dent0d494112014-08-26 13:48:30 +01001501
Chris Dentde456a12014-09-10 12:41:15 +01001502 def list_and_check_container_objects(self, container_name,
1503 present_obj=None,
1504 not_present_obj=None):
Ken'ichi Ohmichic4e4f1c2015-11-17 08:16:12 +00001505 # List objects for a given container and assert which are present and
1506 # which are not.
Ghanshyam2a180b82014-06-16 13:54:22 +09001507 if present_obj is None:
1508 present_obj = []
1509 if not_present_obj is None:
1510 not_present_obj = []
Chris Dent0d494112014-08-26 13:48:30 +01001511 _, object_list = self.container_client.list_container_contents(
1512 container_name)
1513 if present_obj:
1514 for obj in present_obj:
1515 self.assertIn(obj, object_list)
1516 if not_present_obj:
1517 for obj in not_present_obj:
1518 self.assertNotIn(obj, object_list)
1519
Chris Dentde456a12014-09-10 12:41:15 +01001520 def change_container_acl(self, container_name, acl):
Chris Dent0d494112014-08-26 13:48:30 +01001521 metadata_param = {'metadata_prefix': 'x-container-',
1522 'metadata': {'read': acl}}
1523 self.container_client.update_container_metadata(container_name,
1524 **metadata_param)
1525 resp, _ = self.container_client.list_container_metadata(container_name)
1526 self.assertEqual(resp['x-container-read'], acl)
1527
Chris Dentde456a12014-09-10 12:41:15 +01001528 def download_and_verify(self, container_name, obj_name, expected_data):
Chris Dent0d494112014-08-26 13:48:30 +01001529 _, obj = self.object_client.get_object(container_name, obj_name)
1530 self.assertEqual(obj, expected_data)