| Itzik Brown | e67ebb5 | 2016-05-15 05:34:41 +0000 | [diff] [blame] | 1 | # Copyright 2016 Red Hat, Inc. | 
 | 2 | # All Rights Reserved. | 
 | 3 | # | 
 | 4 | #    Licensed under the Apache License, Version 2.0 (the "License"); you may | 
 | 5 | #    not use this file except in compliance with the License. You may obtain | 
 | 6 | #    a copy of the License at | 
 | 7 | # | 
 | 8 | #         http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 | # | 
 | 10 | #    Unless required by applicable law or agreed to in writing, software | 
 | 11 | #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | 
 | 12 | #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | 
 | 13 | #    License for the specific language governing permissions and limitations | 
 | 14 | #    under the License. | 
| Itzik Brown | e67ebb5 | 2016-05-15 05:34:41 +0000 | [diff] [blame] | 15 |  | 
| Alex Stafeyev | c4d9c35 | 2016-12-12 04:13:33 -0500 | [diff] [blame] | 16 | from oslo_log import log | 
 | 17 |  | 
| Itzik Brown | e67ebb5 | 2016-05-15 05:34:41 +0000 | [diff] [blame] | 18 | from tempest.common import waiters | 
 | 19 | from tempest.lib.common import ssh | 
 | 20 | from tempest.lib.common.utils import data_utils | 
 | 21 |  | 
 | 22 | from neutron.tests.tempest.api import base as base_api | 
 | 23 | from neutron.tests.tempest import config | 
 | 24 | from neutron.tests.tempest.scenario import constants | 
 | 25 |  | 
 | 26 | CONF = config.CONF | 
| Itzik Brown | e67ebb5 | 2016-05-15 05:34:41 +0000 | [diff] [blame] | 27 |  | 
| Alex Stafeyev | c4d9c35 | 2016-12-12 04:13:33 -0500 | [diff] [blame] | 28 | LOG = log.getLogger(__name__) | 
 | 29 |  | 
| Itzik Brown | e67ebb5 | 2016-05-15 05:34:41 +0000 | [diff] [blame] | 30 |  | 
 | 31 | class BaseTempestTestCase(base_api.BaseNetworkTest): | 
 | 32 |     @classmethod | 
 | 33 |     def resource_setup(cls): | 
 | 34 |         super(BaseTempestTestCase, cls).resource_setup() | 
 | 35 |  | 
 | 36 |         cls.servers = [] | 
 | 37 |         cls.keypairs = [] | 
 | 38 |  | 
 | 39 |     @classmethod | 
 | 40 |     def resource_cleanup(cls): | 
 | 41 |         for server in cls.servers: | 
 | 42 |             cls.manager.servers_client.delete_server(server) | 
 | 43 |             waiters.wait_for_server_termination(cls.manager.servers_client, | 
 | 44 |                                                 server) | 
 | 45 |  | 
 | 46 |         for keypair in cls.keypairs: | 
 | 47 |             cls.manager.keypairs_client.delete_keypair( | 
 | 48 |                 keypair_name=keypair['name']) | 
 | 49 |  | 
 | 50 |         super(BaseTempestTestCase, cls).resource_cleanup() | 
 | 51 |  | 
 | 52 |     @classmethod | 
 | 53 |     def create_server(cls, flavor_ref, image_ref, key_name, networks, | 
| Itzik Brown | bac51dc | 2016-10-31 12:25:04 +0000 | [diff] [blame] | 54 |                       name=None, security_groups=None): | 
 | 55 |         """Create a server using tempest lib | 
 | 56 |         All the parameters are the ones used in Compute API | 
 | 57 |  | 
 | 58 |         Args: | 
 | 59 |            flavor_ref(str): The flavor of the server to be provisioned. | 
 | 60 |            image_ref(str):  The image of the server to be provisioned. | 
 | 61 |            key_name(str): SSH key to to be used to connect to the | 
 | 62 |                             provisioned server. | 
 | 63 |            networks(list): List of dictionaries where each represent | 
 | 64 |                an interface to be attached to the server. For network | 
 | 65 |                it should be {'uuid': network_uuid} and for port it should | 
 | 66 |                be {'port': port_uuid} | 
 | 67 |            name(str): Name of the server to be provisioned. | 
 | 68 |            security_groups(list): List of dictionaries where | 
 | 69 |                 the keys is 'name' and the value is the name of | 
 | 70 |                 the security group. If it's not passed the default | 
 | 71 |                 security group will be used. | 
 | 72 |         """ | 
 | 73 |  | 
| Itzik Brown | e67ebb5 | 2016-05-15 05:34:41 +0000 | [diff] [blame] | 74 |         name = name or data_utils.rand_name('server-test') | 
| Itzik Brown | bac51dc | 2016-10-31 12:25:04 +0000 | [diff] [blame] | 75 |         if not security_groups: | 
 | 76 |             security_groups = [{'name': 'default'}] | 
 | 77 |  | 
| Itzik Brown | e67ebb5 | 2016-05-15 05:34:41 +0000 | [diff] [blame] | 78 |         server = cls.manager.servers_client.create_server( | 
| Itzik Brown | bac51dc | 2016-10-31 12:25:04 +0000 | [diff] [blame] | 79 |             name=name, | 
 | 80 |             flavorRef=flavor_ref, | 
| Itzik Brown | e67ebb5 | 2016-05-15 05:34:41 +0000 | [diff] [blame] | 81 |             imageRef=image_ref, | 
 | 82 |             key_name=key_name, | 
| Itzik Brown | bac51dc | 2016-10-31 12:25:04 +0000 | [diff] [blame] | 83 |             networks=networks, | 
 | 84 |             security_groups=security_groups) | 
| Itzik Brown | e67ebb5 | 2016-05-15 05:34:41 +0000 | [diff] [blame] | 85 |         cls.servers.append(server['server']['id']) | 
 | 86 |         return server | 
 | 87 |  | 
 | 88 |     @classmethod | 
 | 89 |     def create_keypair(cls, client=None): | 
 | 90 |         client = client or cls.manager.keypairs_client | 
 | 91 |         name = data_utils.rand_name('keypair-test') | 
 | 92 |         body = client.create_keypair(name=name) | 
 | 93 |         cls.keypairs.append(body['keypair']) | 
 | 94 |         return body['keypair'] | 
 | 95 |  | 
 | 96 |     @classmethod | 
| Itzik Brown | 1ef813a | 2016-06-06 12:56:21 +0000 | [diff] [blame] | 97 |     def create_secgroup_rules(cls, rule_list, secgroup_id=None): | 
| Itzik Brown | e67ebb5 | 2016-05-15 05:34:41 +0000 | [diff] [blame] | 98 |         client = cls.manager.network_client | 
 | 99 |         if not secgroup_id: | 
 | 100 |             sgs = client.list_security_groups()['security_groups'] | 
 | 101 |             for sg in sgs: | 
 | 102 |                 if sg['name'] == constants.DEFAULT_SECURITY_GROUP: | 
 | 103 |                     secgroup_id = sg['id'] | 
 | 104 |                     break | 
 | 105 |  | 
| Itzik Brown | 1ef813a | 2016-06-06 12:56:21 +0000 | [diff] [blame] | 106 |         for rule in rule_list: | 
 | 107 |             direction = rule.pop('direction') | 
 | 108 |             client.create_security_group_rule( | 
 | 109 |                 direction=direction, | 
 | 110 |                 security_group_id=secgroup_id, | 
 | 111 |                 **rule) | 
 | 112 |  | 
 | 113 |     @classmethod | 
 | 114 |     def create_loginable_secgroup_rule(cls, secgroup_id=None): | 
 | 115 |         """This rule is intended to permit inbound ssh | 
 | 116 |  | 
 | 117 |         Allowing ssh traffic traffic from all sources, so no group_id is | 
 | 118 |         provided. | 
 | 119 |         Setting a group_id would only permit traffic from ports | 
 | 120 |         belonging to the same security group. | 
 | 121 |         """ | 
 | 122 |  | 
 | 123 |         rule_list = [{'protocol': 'tcp', | 
 | 124 |                       'direction': 'ingress', | 
 | 125 |                       'port_range_min': 22, | 
 | 126 |                       'port_range_max': 22, | 
 | 127 |                       'remote_ip_prefix': '0.0.0.0/0'}] | 
 | 128 |         cls.create_secgroup_rules(rule_list, secgroup_id=secgroup_id) | 
| Itzik Brown | e67ebb5 | 2016-05-15 05:34:41 +0000 | [diff] [blame] | 129 |  | 
 | 130 |     @classmethod | 
 | 131 |     def create_router_and_interface(cls, subnet_id): | 
 | 132 |         router = cls.create_router( | 
 | 133 |             data_utils.rand_name('router'), admin_state_up=True, | 
 | 134 |             external_network_id=CONF.network.public_network_id) | 
| Alex Stafeyev | c4d9c35 | 2016-12-12 04:13:33 -0500 | [diff] [blame] | 135 |         LOG.debug("Created router %s", router['name']) | 
| Itzik Brown | e67ebb5 | 2016-05-15 05:34:41 +0000 | [diff] [blame] | 136 |         cls.create_router_interface(router['id'], subnet_id) | 
 | 137 |         cls.routers.append(router) | 
 | 138 |         return router | 
 | 139 |  | 
 | 140 |     @classmethod | 
 | 141 |     def create_and_associate_floatingip(cls, port_id): | 
 | 142 |         fip = cls.manager.network_client.create_floatingip( | 
 | 143 |             CONF.network.public_network_id, | 
 | 144 |             port_id=port_id)['floatingip'] | 
 | 145 |         cls.floating_ips.append(fip) | 
 | 146 |         return fip | 
 | 147 |  | 
 | 148 |     @classmethod | 
 | 149 |     def check_connectivity(cls, host, ssh_user, ssh_key=None): | 
 | 150 |         ssh_client = ssh.Client(host, ssh_user, pkey=ssh_key) | 
 | 151 |         ssh_client.test_connection_auth() | 
| Itzik Brown | 1ef813a | 2016-06-06 12:56:21 +0000 | [diff] [blame] | 152 |  | 
 | 153 |     @classmethod | 
 | 154 |     def setup_network_and_server(cls): | 
| Itzik Brown | bac51dc | 2016-10-31 12:25:04 +0000 | [diff] [blame] | 155 |         """Creating network resources and a server. | 
 | 156 |  | 
 | 157 |         Creating a network, subnet, router, keypair, security group | 
 | 158 |         and a server. | 
 | 159 |         """ | 
| Itzik Brown | 1ef813a | 2016-06-06 12:56:21 +0000 | [diff] [blame] | 160 |         cls.network = cls.create_network() | 
| Alex Stafeyev | c4d9c35 | 2016-12-12 04:13:33 -0500 | [diff] [blame] | 161 |         LOG.debug("Created network %s", cls.network['name']) | 
| Itzik Brown | 1ef813a | 2016-06-06 12:56:21 +0000 | [diff] [blame] | 162 |         cls.subnet = cls.create_subnet(cls.network) | 
| Alex Stafeyev | c4d9c35 | 2016-12-12 04:13:33 -0500 | [diff] [blame] | 163 |         LOG.debug("Created subnet %s", cls.subnet['id']) | 
| Itzik Brown | 1ef813a | 2016-06-06 12:56:21 +0000 | [diff] [blame] | 164 |  | 
| Itzik Brown | bac51dc | 2016-10-31 12:25:04 +0000 | [diff] [blame] | 165 |         secgroup = cls.manager.network_client.create_security_group( | 
 | 166 |             name=data_utils.rand_name('secgroup-')) | 
| Alex Stafeyev | c4d9c35 | 2016-12-12 04:13:33 -0500 | [diff] [blame] | 167 |         LOG.debug("Created security group %s", | 
 | 168 |                   secgroup['security_group']['name']) | 
| Itzik Brown | bac51dc | 2016-10-31 12:25:04 +0000 | [diff] [blame] | 169 |         cls.security_groups.append(secgroup['security_group']) | 
 | 170 |  | 
| Itzik Brown | 1ef813a | 2016-06-06 12:56:21 +0000 | [diff] [blame] | 171 |         cls.create_router_and_interface(cls.subnet['id']) | 
 | 172 |         cls.keypair = cls.create_keypair() | 
| Itzik Brown | bac51dc | 2016-10-31 12:25:04 +0000 | [diff] [blame] | 173 |         cls.create_loginable_secgroup_rule( | 
 | 174 |             secgroup_id=secgroup['security_group']['id']) | 
| Itzik Brown | 1ef813a | 2016-06-06 12:56:21 +0000 | [diff] [blame] | 175 |         cls.server = cls.create_server( | 
 | 176 |             flavor_ref=CONF.compute.flavor_ref, | 
 | 177 |             image_ref=CONF.compute.image_ref, | 
 | 178 |             key_name=cls.keypair['name'], | 
| Itzik Brown | bac51dc | 2016-10-31 12:25:04 +0000 | [diff] [blame] | 179 |             networks=[{'uuid': cls.network['id']}], | 
 | 180 |             security_groups=[{'name': secgroup['security_group']['name']}]) | 
| Itzik Brown | 1ef813a | 2016-06-06 12:56:21 +0000 | [diff] [blame] | 181 |         waiters.wait_for_server_status(cls.manager.servers_client, | 
 | 182 |                                        cls.server['server']['id'], | 
 | 183 |                                        constants.SERVER_STATUS_ACTIVE) | 
 | 184 |         port = cls.client.list_ports(network_id=cls.network['id'], | 
 | 185 |                                      device_id=cls.server[ | 
 | 186 |                                           'server']['id'])['ports'][0] | 
 | 187 |         cls.fip = cls.create_and_associate_floatingip(port['id']) |