blob: ae9d584148f5afcdccfe01a25b176a36d00b432f [file] [log] [blame]
nithya-ganesan222efd72015-01-22 12:20:27 +00001# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
14from oslo_log import log as logging
15
Ken'ichi Ohmichief1c1ce2017-03-10 11:07:10 -080016from tempest.lib.common.utils import data_utils
Andrea Frittoli (andreaf)db9672e2016-02-23 14:07:24 -050017from tempest.lib import exceptions as lib_exc
Andrea Frittoli (andreaf)8def7ca2015-05-13 14:24:19 +010018
nithya-ganesan222efd72015-01-22 12:20:27 +000019LOG = logging.getLogger(__name__)
20
21
Andrea Frittoli8871fca2017-08-10 23:43:25 +010022def _network_service(clients, use_neutron):
Andrea Frittoli557320e2017-08-09 21:08:08 +010023 # Internal helper to select the right network clients
Andrea Frittoli463a8a62017-08-09 16:55:33 +010024 if use_neutron:
Andrea Frittoli8871fca2017-08-10 23:43:25 +010025 return clients.network
Andrea Frittoli463a8a62017-08-09 16:55:33 +010026 else:
Andrea Frittoli8871fca2017-08-10 23:43:25 +010027 return clients.compute
Matthew Treinish861619c2016-06-16 17:11:49 -040028
29
Andrea Frittoli8871fca2017-08-10 23:43:25 +010030def create_ssh_security_group(clients, add_rule=False, ethertype='IPv4',
Andrea Frittoli1fa7a602017-08-09 16:28:55 +010031 use_neutron=True):
Andrea Frittoli557320e2017-08-09 21:08:08 +010032 """Create a security group for ping/ssh testing
33
34 Create a security group to be attached to a VM using the nova or neutron
35 clients. If rules are added, the group can be attached to a VM to enable
36 connectivity validation over ICMP and further testing over SSH.
37
Andrea Frittoli8871fca2017-08-10 23:43:25 +010038 :param clients: Instance of `tempest.lib.services.clients.ServiceClients`
39 or of a subclass of it. Resources are provisioned using clients from
40 `clients`.
Andrea Frittoli557320e2017-08-09 21:08:08 +010041 :param add_rule: Whether security group rules are provisioned or not.
42 Defaults to `False`.
43 :param ethertype: 'IPv4' or 'IPv6'. Honoured only in case neutron is used.
44 :param use_neutron: When True resources are provisioned via neutron, when
45 False resources are provisioned via nova.
46 :returns: A dictionary with the security group as returned by the API.
47
48 Examples::
49
50 from tempest.common import validation_resources as vr
51 from tempest.lib import auth
52 from tempest.lib.services import clients
53
54 creds = auth.get_credentials('http://mycloud/identity/v3',
55 username='me', project_name='me',
56 password='secret', domain_name='Default')
Andrea Frittoli8871fca2017-08-10 23:43:25 +010057 osclients = clients.ServiceClients(creds, 'http://mycloud/identity/v3')
Andrea Frittoli557320e2017-08-09 21:08:08 +010058 # Security group for IPv4 tests
Andrea Frittoli8871fca2017-08-10 23:43:25 +010059 sg4 = vr.create_ssh_security_group(osclients, add_rule=True)
Andrea Frittoli557320e2017-08-09 21:08:08 +010060 # Security group for IPv6 tests
Andrea Frittoli8871fca2017-08-10 23:43:25 +010061 sg6 = vr.create_ssh_security_group(osclients, ethertype='IPv6',
62 add_rule=True)
Andrea Frittoli557320e2017-08-09 21:08:08 +010063 """
Andrea Frittoli8871fca2017-08-10 23:43:25 +010064 network_service = _network_service(clients, use_neutron)
Andrea Frittoli463a8a62017-08-09 16:55:33 +010065 security_groups_client = network_service.SecurityGroupsClient()
66 security_group_rules_client = network_service.SecurityGroupRulesClient()
67 # Security Group clients for nova and neutron behave the same
nithya-ganesan222efd72015-01-22 12:20:27 +000068 sg_name = data_utils.rand_name('securitygroup-')
69 sg_description = data_utils.rand_name('description-')
Yaroslav Lobankove5cc9fb2015-08-07 17:30:51 +030070 security_group = security_groups_client.create_security_group(
ghanshyamb610b772015-08-24 17:29:38 +090071 name=sg_name, description=sg_description)['security_group']
Andrea Frittoli463a8a62017-08-09 16:55:33 +010072 # Security Group Rules clients require different parameters depending on
73 # the network service in use
nithya-ganesan222efd72015-01-22 12:20:27 +000074 if add_rule:
Andrea Frittoli1fa7a602017-08-09 16:28:55 +010075 if use_neutron:
Andrea Frittoli463a8a62017-08-09 16:55:33 +010076 security_group_rules_client.create_security_group_rule(
77 security_group_id=security_group['id'],
78 protocol='tcp',
79 ethertype=ethertype,
80 port_range_min=22,
81 port_range_max=22,
82 direction='ingress')
83 security_group_rules_client.create_security_group_rule(
84 security_group_id=security_group['id'],
85 protocol='icmp',
86 ethertype=ethertype,
87 direction='ingress')
Matthew Treinish861619c2016-06-16 17:11:49 -040088 else:
89 security_group_rules_client.create_security_group_rule(
90 parent_group_id=security_group['id'], ip_protocol='tcp',
91 from_port=22, to_port=22)
92 security_group_rules_client.create_security_group_rule(
93 parent_group_id=security_group['id'], ip_protocol='icmp',
94 from_port=-1, to_port=-1)
nithya-ganesan222efd72015-01-22 12:20:27 +000095 LOG.debug("SSH Validation resource security group with tcp and icmp "
Jordan Pittier525ec712016-12-07 17:51:26 +010096 "rules %s created", sg_name)
nithya-ganesan222efd72015-01-22 12:20:27 +000097 return security_group
98
99
Andrea Frittoli8871fca2017-08-10 23:43:25 +0100100def create_validation_resources(clients, keypair=False, floating_ip=False,
101 security_group=False,
102 security_group_rules=False,
Andrea Frittoli1fa7a602017-08-09 16:28:55 +0100103 ethertype='IPv4', use_neutron=True,
104 floating_network_id=None,
105 floating_network_name=None):
Andrea Frittoli557320e2017-08-09 21:08:08 +0100106 """Provision resources for VM ping/ssh testing
107
108 Create resources required to be able to ping / ssh a virtual machine:
109 keypair, security group, security group rules and a floating IP.
110 Which of those resources are required may depend on the cloud setup and on
Andrea Frittoli8871fca2017-08-10 23:43:25 +0100111 the specific test and it can be controlled via the corresponding
112 arguments.
Andrea Frittoli557320e2017-08-09 21:08:08 +0100113
114 Provisioned resources are returned in a dictionary.
115
Andrea Frittoli8871fca2017-08-10 23:43:25 +0100116 :param clients: Instance of `tempest.lib.services.clients.ServiceClients`
117 or of a subclass of it. Resources are provisioned using clients from
118 `clients`.
119 :param keypair: Whether to provision a keypair. Defaults to False.
120 :param floating_ip: Whether to provision a floating IP. Defaults to False.
121 :param security_group: Whether to provision a security group. Defaults to
122 False.
123 :param security_group_rules: Whether to provision security group rules.
124 Defaults to False.
Andrea Frittoli557320e2017-08-09 21:08:08 +0100125 :param ethertype: 'IPv4' or 'IPv6'. Honoured only in case neutron is used.
126 :param use_neutron: When True resources are provisioned via neutron, when
127 False resources are provisioned via nova.
128 :param floating_network_id: The id of the network used to provision a
129 floating IP. Only used if a floating IP is requested and with neutron.
130 :param floating_network_name: The name of the floating IP pool used to
131 provision the floating IP. Only used if a floating IP is requested and
132 with nova-net.
133 :returns: A dictionary with the same keys as the input
134 `validation_resources` and the resources for values in the format
135 they are returned by the API.
136
137 Examples::
138
139 from tempest.common import validation_resources as vr
140 from tempest.lib import auth
141 from tempest.lib.services import clients
142
143 creds = auth.get_credentials('http://mycloud/identity/v3',
144 username='me', project_name='me',
145 password='secret', domain_name='Default')
Andrea Frittoli8871fca2017-08-10 23:43:25 +0100146 osclients = clients.ServiceClients(creds, 'http://mycloud/identity/v3')
Andrea Frittoli557320e2017-08-09 21:08:08 +0100147 # Request keypair and floating IP
148 resources = dict(keypair=True, security_group=False,
149 security_group_rules=False, floating_ip=True)
150 resources = vr.create_validation_resources(
Andrea Frittoli8871fca2017-08-10 23:43:25 +0100151 osclients, use_neutron=True,
152 floating_network_id='4240E68E-23DA-4C82-AC34-9FEFAA24521C',
153 **resources)
Andrea Frittoli557320e2017-08-09 21:08:08 +0100154
155 # The floating IP to be attached to the VM
156 floating_ip = resources['floating_ip']['ip']
157 """
nithya-ganesan222efd72015-01-22 12:20:27 +0000158 # Create and Return the validation resources required to validate a VM
159 validation_data = {}
Andrea Frittoli8871fca2017-08-10 23:43:25 +0100160 if keypair:
161 keypair_name = data_utils.rand_name('keypair')
162 validation_data.update(
163 clients.compute.KeyPairsClient().create_keypair(
ghanshyamdee01f22015-08-17 11:41:47 +0900164 name=keypair_name))
Andrea Frittoli8871fca2017-08-10 23:43:25 +0100165 LOG.debug("Validation resource key %s created", keypair_name)
166 if security_group:
167 validation_data['security_group'] = create_ssh_security_group(
168 clients, add_rule=security_group_rules,
169 use_neutron=use_neutron, ethertype=ethertype)
170 if floating_ip:
171 floating_ip_client = _network_service(
172 clients, use_neutron).FloatingIPsClient()
173 if use_neutron:
174 floatingip = floating_ip_client.create_floatingip(
175 floating_network_id=floating_network_id)
176 # validation_resources['floating_ip'] has historically looked
177 # like a compute API POST /os-floating-ips response, so we need
178 # to mangle it a bit for a Neutron response with different
179 # fields.
180 validation_data['floating_ip'] = floatingip['floatingip']
181 validation_data['floating_ip']['ip'] = (
182 floatingip['floatingip']['floating_ip_address'])
183 else:
184 # NOTE(mriedem): The os-floating-ips compute API was deprecated
185 # in the 2.36 microversion. Any tests for CRUD operations on
186 # floating IPs using the compute API should be capped at 2.35.
187 validation_data.update(floating_ip_client.create_floating_ip(
188 pool=floating_network_name))
nithya-ganesan222efd72015-01-22 12:20:27 +0000189 return validation_data
190
191
Andrea Frittoli8871fca2017-08-10 23:43:25 +0100192def clear_validation_resources(clients, keypair=None, floating_ip=None,
193 security_group=None, use_neutron=True):
Andrea Frittoli557320e2017-08-09 21:08:08 +0100194 """Cleanup resources for VM ping/ssh testing
195
196 Cleanup a set of resources provisioned via `create_validation_resources`.
197 In case of errors during cleanup, the exception is logged and the cleanup
198 process is continued. The first exception that was raised is re-raised
199 after the cleanup is complete.
200
Andrea Frittoli8871fca2017-08-10 23:43:25 +0100201 :param clients: Instance of `tempest.lib.services.clients.ServiceClients`
202 or of a subclass of it. Resources are provisioned using clients from
203 `clients`.
204 :param keypair: A dictionary with the keypair to be deleted. Defaults to
205 None.
206 :param floating_ip: A dictionary with the floating_ip to be deleted.
207 Defaults to None.
208 :param security_group: A dictionary with the security_group to be deleted.
209 Defaults to None.
Andrea Frittoli557320e2017-08-09 21:08:08 +0100210 :param use_neutron: When True resources are provisioned via neutron, when
211 False resources are provisioned via nova.
212 :returns: A dictionary with the same keys as the input
213 `validation_resources` and the resources for values in the format
214 they are returned by the API.
215
216 Examples::
217
218 from tempest.common import validation_resources as vr
219 from tempest.lib import auth
220 from tempest.lib.services import clients
221
222 creds = auth.get_credentials('http://mycloud/identity/v3',
223 username='me', project_name='me',
224 password='secret', domain_name='Default')
Andrea Frittoli8871fca2017-08-10 23:43:25 +0100225 osclients = clients.ServiceClients(creds, 'http://mycloud/identity/v3')
Andrea Frittoli557320e2017-08-09 21:08:08 +0100226 # Request keypair and floating IP
227 resources = dict(keypair=True, security_group=False,
228 security_group_rules=False, floating_ip=True)
229 resources = vr.create_validation_resources(
Andrea Frittoli8871fca2017-08-10 23:43:25 +0100230 osclients, validation_resources=resources, use_neutron=True,
Andrea Frittoli557320e2017-08-09 21:08:08 +0100231 floating_network_id='4240E68E-23DA-4C82-AC34-9FEFAA24521C')
232
233 # Now cleanup the resources
234 try:
Andrea Frittoli8871fca2017-08-10 23:43:25 +0100235 vr.clear_validation_resources(osclients, use_neutron=True,
236 **resources)
Andrea Frittoli557320e2017-08-09 21:08:08 +0100237 except Exception as e:
238 LOG.exception('Something went wrong during cleanup, ignoring')
239 """
nithya-ganesan222efd72015-01-22 12:20:27 +0000240 has_exception = None
Andrea Frittoli8871fca2017-08-10 23:43:25 +0100241 if keypair:
242 keypair_client = clients.compute.KeyPairsClient()
243 keypair_name = keypair['name']
244 try:
245 keypair_client.delete_keypair(keypair_name)
246 except lib_exc.NotFound:
247 LOG.warning(
248 "Keypair %s is not found when attempting to delete",
249 keypair_name
250 )
251 except Exception as exc:
252 LOG.exception('Exception raised while deleting key %s',
253 keypair_name)
254 if not has_exception:
255 has_exception = exc
256 network_service = _network_service(clients, use_neutron)
257 if security_group:
258 security_group_client = network_service.SecurityGroupsClient()
259 sec_id = security_group['id']
260 try:
261 security_group_client.delete_security_group(sec_id)
262 security_group_client.wait_for_resource_deletion(sec_id)
263 except lib_exc.NotFound:
264 LOG.warning("Security group %s is not found when attempting "
265 "to delete", sec_id)
266 except lib_exc.Conflict as exc:
267 LOG.exception('Conflict while deleting security '
268 'group %s VM might not be deleted', sec_id)
269 if not has_exception:
270 has_exception = exc
271 except Exception as exc:
272 LOG.exception('Exception raised while deleting security '
273 'group %s', sec_id)
274 if not has_exception:
275 has_exception = exc
276 if floating_ip:
277 floating_ip_client = network_service.FloatingIPsClient()
278 fip_id = floating_ip['id']
279 try:
280 if use_neutron:
281 floating_ip_client.delete_floatingip(fip_id)
282 else:
283 floating_ip_client.delete_floating_ip(fip_id)
284 except lib_exc.NotFound:
285 LOG.warning('Floating ip %s not found while attempting to '
286 'delete', fip_id)
287 except Exception as exc:
288 LOG.exception('Exception raised while deleting ip %s', fip_id)
289 if not has_exception:
290 has_exception = exc
nithya-ganesan222efd72015-01-22 12:20:27 +0000291 if has_exception:
292 raise has_exception