Browse Source

Fix deprecated API usage of keystone client

* Use keystoneauth1 for making session, which is shared throw all clients
* KeystoneClient is now only wrapper over session
Requirements has been updated to meet global requirements for mitaka release:
1. Bumped clients versions
2. requests has blacklisted versions due to bugs

Closes-bug: #1571611

Change-Id: Icc59761b590b76a8d3ddac9b4f219efc097447a5
(cherry picked from commit 94170e0)
changes/61/340361/3
Alexey Stepanov 3 years ago
parent
commit
c28d12604b
4 changed files with 233 additions and 165 deletions
  1. 152
    113
      fuelweb_test/helpers/common.py
  2. 39
    18
      fuelweb_test/helpers/http.py
  3. 26
    23
      fuelweb_test/helpers/os_actions.py
  4. 16
    11
      fuelweb_test/requirements.txt

+ 152
- 113
fuelweb_test/helpers/common.py View File

@@ -12,21 +12,33 @@
12 12
 #    License for the specific language governing permissions and limitations
13 13
 #    under the License.
14 14
 
15
+import sys
15 16
 import time
16
-from urlparse import urlparse
17
+import traceback
17 18
 
18
-from cinderclient import client as cinderclient
19
+from cinderclient.client import Client as CinderClient
19 20
 from heatclient.v1.client import Client as HeatClient
20 21
 from glanceclient.v1 import Client as GlanceClient
21
-import ironicclient.client as ironicclient
22
+from ironicclient.client import Client as IronicClient
23
+from keystoneauth1.exceptions import ClientException
24
+from keystoneauth1.identity import V2Password
25
+from keystoneauth1.session import Session as KeystoneSession
22 26
 from keystoneclient.v2_0 import Client as KeystoneClient
23
-from keystoneclient.exceptions import ClientException
24
-from novaclient.v2 import Client as NovaClient
25
-import neutronclient.v2_0.client as neutronclient
27
+from novaclient.client import Client as NovaClient
28
+from neutronclient.v2_0.client import Client as NeutronClient
26 29
 from proboscis.asserts import assert_equal
27
-
28
-from fuelweb_test import logger as LOGGER
29
-from fuelweb_test import logwrap as LOGWRAP
30
+import six
31
+# pylint: disable=redefined-builtin
32
+# noinspection PyUnresolvedReferences
33
+from six.moves import xrange
34
+# pylint: enable=redefined-builtin
35
+# pylint: disable=import-error
36
+# noinspection PyUnresolvedReferences
37
+from six.moves import urllib
38
+# pylint: enable=import-error
39
+
40
+from fuelweb_test import logger
41
+from fuelweb_test import logwrap
30 42
 from fuelweb_test.settings import DISABLE_SSL
31 43
 from fuelweb_test.settings import PATH_TO_CERT
32 44
 from fuelweb_test.settings import VERIFY_SSL
@@ -35,14 +47,16 @@ from fuelweb_test.settings import VERIFY_SSL
35 47
 class Common(object):
36 48
     """Common."""  # TODO documentation
37 49
 
50
+    def __make_endpoint(self, endpoint):
51
+        parse = urllib.parse.urlparse(endpoint)
52
+        return parse._replace(
53
+            netloc='{}:{}'.format(
54
+                self.controller_ip, parse.port)).geturl()
55
+
38 56
     def __init__(self, controller_ip, user, password, tenant):
39 57
         self.controller_ip = controller_ip
40 58
 
41
-        def make_endpoint(endpoint):
42
-            parse = urlparse(endpoint)
43
-            return parse._replace(
44
-                netloc='{}:{}'.format(
45
-                    self.controller_ip, parse.port)).geturl()
59
+        self.keystone_session = None
46 60
 
47 61
         if DISABLE_SSL:
48 62
             auth_url = 'http://{0}:5000/v2.0/'.format(self.controller_ip)
@@ -53,79 +67,100 @@ class Common(object):
53 67
 
54 68
         insecure = not VERIFY_SSL
55 69
 
56
-        LOGGER.debug('Auth URL is {0}'.format(auth_url))
57
-
58
-        keystone_args = {'username': user, 'password': password,
59
-                         'tenant_name': tenant, 'auth_url': auth_url,
60
-                         'ca_cert': path_to_cert, 'insecure': insecure}
61
-        self.keystone = self._get_keystoneclient(**keystone_args)
62
-
63
-        token = self.keystone.auth_token
64
-        LOGGER.debug('Token is {0}'.format(token))
65
-
66
-        neutron_endpoint = self.keystone.service_catalog.url_for(
67
-            service_type='network', endpoint_type='publicURL')
68
-        neutron_args = {'username': user, 'password': password,
69
-                        'tenant_name': tenant, 'auth_url': auth_url,
70
-                        'ca_cert': path_to_cert, 'insecure': insecure,
71
-                        'endpoint_url': make_endpoint(neutron_endpoint)}
72
-        self.neutron = neutronclient.Client(**neutron_args)
73
-
74
-        nova_endpoint = self.keystone.service_catalog.url_for(
75
-            service_type='compute', endpoint_type='publicURL')
76
-        nova_args = {'username': user, 'api_key': password,
77
-                     'project_id': tenant, 'auth_url': auth_url,
78
-                     'cacert': path_to_cert, 'insecure': insecure,
79
-                     'bypass_url': make_endpoint(nova_endpoint),
80
-                     'auth_token': token}
81
-        self.nova = NovaClient(**nova_args)
82
-
83
-        cinder_endpoint = self.keystone.service_catalog.url_for(
84
-            service_type='volume', endpoint_type='publicURL')
85
-        cinder_args = {'version': 1, 'username': user,
86
-                       'api_key': password, 'project_id': tenant,
87
-                       'auth_url': auth_url, 'cacert': path_to_cert,
88
-                       'insecure': insecure,
89
-                       'bypass_url': make_endpoint(cinder_endpoint)}
90
-        self.cinder = cinderclient.Client(**cinder_args)
91
-
92
-        glance_endpoint = self.keystone.service_catalog.url_for(
93
-            service_type='image', endpoint_type='publicURL')
94
-        LOGGER.debug('Glance endpoint is {0}'.format(
95
-            make_endpoint(glance_endpoint)))
96
-        glance_args = {'endpoint': make_endpoint(glance_endpoint),
97
-                       'token': token,
98
-                       'cacert': path_to_cert,
99
-                       'insecure': insecure}
100
-        self.glance = GlanceClient(**glance_args)
101
-
102
-        heat_endpoint = self.keystone.service_catalog.url_for(
103
-            service_type='orchestration', endpoint_type='publicURL')
104
-
105
-        heat_args = {'endpoint': make_endpoint(heat_endpoint),
106
-                     'token': token,
107
-                     'cacert': path_to_cert,
108
-                     'insecure': insecure}
109
-        self.heat = HeatClient(**heat_args)
110
-
70
+        logger.debug('Auth URL is {0}'.format(auth_url))
71
+
72
+        self.__keystone_auth = V2Password(
73
+            auth_url=auth_url,
74
+            username=user,
75
+            password=password,
76
+            tenant_name=tenant)  # TODO: in v3 project_name
77
+
78
+        self.__start_keystone_session(ca_cert=path_to_cert, insecure=insecure)
79
+
80
+    @property
81
+    def keystone(self):
82
+        return KeystoneClient(session=self.keystone_session)
83
+
84
+    @property
85
+    def glance(self):
86
+        endpoint = self.__make_endpoint(
87
+            self._get_url_for_svc(service_type='image'))
88
+        return GlanceClient(
89
+            session=self.keystone_session,
90
+            endpoint=endpoint,
91
+            endpoint_override=endpoint)
92
+
93
+    @property
94
+    def neutron(self):
95
+        endpoint = self.__make_endpoint(
96
+            self._get_url_for_svc(service_type='network'))
97
+        return NeutronClient(
98
+            session=self.keystone_session,
99
+            endpoint_override=endpoint)
100
+
101
+    @property
102
+    def nova(self):
103
+        endpoint = self.__make_endpoint(
104
+            self._get_url_for_svc(service_type='compute'))
105
+        return NovaClient(
106
+            version='2',
107
+            session=self.keystone_session,
108
+            endpoint_override=endpoint)
109
+
110
+    @property
111
+    def cinder(self):
112
+        endpoint = self.__make_endpoint(
113
+            self._get_url_for_svc(service_type='volume'))
114
+        return CinderClient(
115
+            version='1',
116
+            session=self.keystone_session,
117
+            endpoint_override=endpoint)
118
+
119
+    @property
120
+    def heat(self):
121
+        endpoint = self.__make_endpoint(
122
+            self._get_url_for_svc(service_type='orchestration'))
123
+        return HeatClient(
124
+            session=self.keystone_session,
125
+            endpoint_override=endpoint)
126
+
127
+    @property
128
+    def ironic(self):
111 129
         try:
112
-            ironic_endpoint = self.keystone.service_catalog.url_for(
113
-                service_type='baremetal',
114
-                endpoint_type='publicURL')
115
-            self.ironic = ironicclient.get_client(
116
-                api_version=1,
117
-                os_auth_token=token,
118
-                ironic_url=make_endpoint(ironic_endpoint), insecure=True)
130
+            endpoint = self.__make_endpoint(
131
+                self._get_url_for_svc(service_type='baremetal'))
132
+            return IronicClient(
133
+                version='1',
134
+                session=self.keystone_session,
135
+                insecure=True,
136
+                endpoint_override=endpoint
137
+            )
119 138
         except ClientException as e:
120
-            LOGGER.warning('Could not initialize ironic client {0}'.format(e))
139
+            logger.warning('Could not initialize ironic client {0}'.format(e))
140
+            raise
141
+
142
+    @property
143
+    def keystone_access(self):
144
+        return self.__keystone_auth.get_access(session=self.keystone_session)
145
+
146
+    def _get_url_for_svc(
147
+            self, service_type=None, interface='public',
148
+            region_name=None, service_name=None,
149
+            service_id=None, endpoint_id=None
150
+    ):
151
+        return self.keystone_access.service_catalog.url_for(
152
+            service_type=service_type, interface=interface,
153
+            region_name=region_name, service_name=service_name,
154
+            service_id=service_id, endpoint_id=endpoint_id
155
+        )
121 156
 
122 157
     def goodbye_security(self):
123 158
         secgroup_list = self.nova.security_groups.list()
124
-        LOGGER.debug("Security list is {0}".format(secgroup_list))
159
+        logger.debug("Security list is {0}".format(secgroup_list))
125 160
         secgroup_id = [i.id for i in secgroup_list if i.name == 'default'][0]
126
-        LOGGER.debug("Id of security group default is {0}".format(
161
+        logger.debug("Id of security group default is {0}".format(
127 162
             secgroup_id))
128
-        LOGGER.debug('Permit all TCP and ICMP in security group default')
163
+        logger.debug('Permit all TCP and ICMP in security group default')
129 164
         self.nova.security_group_rules.create(secgroup_id,
130 165
                                               ip_protocol='tcp',
131 166
                                               from_port=1,
@@ -143,15 +178,16 @@ class Common(object):
143 178
         return self.glance.images.delete(image_id)
144 179
 
145 180
     def create_key(self, key_name):
146
-        LOGGER.debug('Try to create key {0}'.format(key_name))
181
+        logger.debug('Try to create key {0}'.format(key_name))
147 182
         return self.nova.keypairs.create(key_name)
148 183
 
149 184
     def create_instance(self, flavor_name='test_flavor', ram=64, vcpus=1,
150 185
                         disk=1, server_name='test_instance', image_name=None,
151 186
                         neutron_network=True, label=None):
152
-        LOGGER.debug('Try to create instance')
187
+        logger.debug('Try to create instance')
153 188
 
154 189
         start_time = time.time()
190
+        exc_type, exc_value, exc_traceback = None, None, None
155 191
         while time.time() - start_time < 100:
156 192
             try:
157 193
                 if image_name:
@@ -160,9 +196,13 @@ class Common(object):
160 196
                 else:
161 197
                     image = [i.id for i in self.nova.images.list()]
162 198
                 break
163
-            except:
164
-                pass
199
+            except Exception as e:
200
+                exc_type, exc_value, exc_traceback = sys.exc_info()
201
+                logger.warning('Ignoring exception: {!r}'.format(e))
202
+                logger.debug(traceback.format_exc())
165 203
         else:
204
+            if all((exc_type, exc_traceback, exc_value)):
205
+                six.reraise(exc_type, exc_value, exc_traceback)
166 206
             raise Exception('Can not get image')
167 207
 
168 208
         kwargs = {}
@@ -171,16 +211,16 @@ class Common(object):
171 211
             network = self.nova.networks.find(label=net_label)
172 212
             kwargs['nics'] = [{'net-id': network.id, 'v4-fixed-ip': ''}]
173 213
 
174
-        LOGGER.info('image uuid is {0}'.format(image))
214
+        logger.info('image uuid is {0}'.format(image))
175 215
         flavor = self.nova.flavors.create(
176 216
             name=flavor_name, ram=ram, vcpus=vcpus, disk=disk)
177
-        LOGGER.info('flavor is {0}'.format(flavor.name))
217
+        logger.info('flavor is {0}'.format(flavor.name))
178 218
         server = self.nova.servers.create(
179 219
             name=server_name, image=image[0], flavor=flavor, **kwargs)
180
-        LOGGER.info('server is {0}'.format(server.name))
220
+        logger.info('server is {0}'.format(server.name))
181 221
         return server
182 222
 
183
-    @LOGWRAP
223
+    @logwrap
184 224
     def get_instance_detail(self, server):
185 225
         details = self.nova.servers.get(server)
186 226
         return details
@@ -193,13 +233,13 @@ class Common(object):
193 233
         try:
194 234
             _verify_instance_state()
195 235
         except AssertionError:
196
-            LOGGER.debug('Instance is not {0}, lets provide it the last '
236
+            logger.debug('Instance is not {0}, lets provide it the last '
197 237
                          'chance and sleep 60 sec'.format(expected_state))
198 238
             time.sleep(60)
199 239
             _verify_instance_state()
200 240
 
201 241
     def delete_instance(self, server):
202
-        LOGGER.debug('Try to delete instance')
242
+        logger.debug('Try to delete instance')
203 243
         self.nova.servers.delete(server)
204 244
 
205 245
     def create_flavor(self, name, ram, vcpus, disk, flavorid="auto",
@@ -211,29 +251,28 @@ class Common(object):
211 251
     def delete_flavor(self, flavor):
212 252
         return self.nova.flavors.delete(flavor)
213 253
 
214
-    def _get_keystoneclient(self, username, password, tenant_name, auth_url,
215
-                            retries=3, ca_cert=None, insecure=False):
216
-        keystone = None
217
-        for i in range(retries):
254
+    def __start_keystone_session(
255
+            self, retries=3, ca_cert=None, insecure=not VERIFY_SSL):
256
+        exc_type, exc_value, exc_traceback = None, None, None
257
+        for i in xrange(retries):
218 258
             try:
219
-                if ca_cert:
220
-                    keystone = KeystoneClient(username=username,
221
-                                              password=password,
222
-                                              tenant_name=tenant_name,
223
-                                              auth_url=auth_url,
224
-                                              cacert=ca_cert,
225
-                                              insecure=insecure)
226
-
259
+                if insecure:
260
+                    self.keystone_session = KeystoneSession(
261
+                        auth=self.__keystone_auth, verify=False)
262
+                elif ca_cert:
263
+                    self.keystone_session = KeystoneSession(
264
+                        auth=self.__keystone_auth, verify=ca_cert)
227 265
                 else:
228
-                    keystone = KeystoneClient(username=username,
229
-                                              password=password,
230
-                                              tenant_name=tenant_name,
231
-                                              auth_url=auth_url)
232
-                break
233
-            except ClientException as e:
234
-                err = "Try nr {0}. Could not get keystone client, error: {1}"
235
-                LOGGER.warning(err.format(i + 1, e))
266
+                    self.keystone_session = KeystoneSession(
267
+                        auth=self.__keystone_auth)
268
+                self.keystone_session.get_auth_headers()
269
+                return
270
+
271
+            except ClientException as exc:
272
+                exc_type, exc_value, exc_traceback = sys.exc_info()
273
+                err = "Try nr {0}. Could not get keystone token, error: {1}"
274
+                logger.warning(err.format(i + 1, exc))
236 275
                 time.sleep(5)
237
-        if not keystone:
238
-            raise
239
-        return keystone
276
+        if exc_type and exc_traceback and exc_value:
277
+            six.reraise(exc_type, exc_value, exc_traceback)
278
+        raise RuntimeError()

+ 39
- 18
fuelweb_test/helpers/http.py View File

@@ -14,10 +14,19 @@
14 14
 
15 15
 import json
16 16
 import traceback
17
-import urllib2
18 17
 
18
+from keystoneauth1 import exceptions
19
+from keystoneauth1.identity import V2Password
20
+from keystoneauth1.session import Session as KeystoneSession
19 21
 from keystoneclient.v2_0 import Client as KeystoneClient
20
-from keystoneclient import exceptions
22
+# pylint: disable=import-error
23
+# noinspection PyUnresolvedReferences
24
+from six.moves.urllib import request
25
+# noinspection PyUnresolvedReferences
26
+from six.moves.urllib.error import HTTPError
27
+# pylint: enable=import-error
28
+import requests
29
+
21 30
 from fuelweb_test import logger
22 31
 
23 32
 
@@ -30,17 +39,21 @@ class HTTPClient(object):
30 39
         self.keystone_url = keystone_url
31 40
         self.creds = dict(credentials, **kwargs)
32 41
         self.keystone = None
33
-        self.opener = urllib2.build_opener(urllib2.HTTPHandler)
42
+        self.session = None
43
+        self.opener = request.build_opener(request.HTTPHandler)
34 44
 
35 45
     def authenticate(self):
36 46
         try:
37 47
             logger.info('Initialize keystoneclient with url %s',
38 48
                         self.keystone_url)
39
-            self.keystone = KeystoneClient(
40
-                auth_url=self.keystone_url, **self.creds)
41
-            # it depends on keystone version, some versions doing auth
42
-            # explicitly some don't, but we are making it explicitly always
43
-            self.keystone.authenticate()
49
+            auth = V2Password(
50
+                auth_url=self.keystone_url,
51
+                username=self.creds['username'],
52
+                password=self.creds['password'],
53
+                tenant_name=self.creds['tenant_name'])
54
+            # TODO: in v3 project_name
55
+            self.session = KeystoneSession(auth=auth, verify=False)
56
+            self.keystone = KeystoneClient(session=self.session)
44 57
             logger.debug('Authorization token is successfully updated')
45 58
         except exceptions.AuthorizationFailure:
46 59
             logger.warning(
@@ -51,7 +64,7 @@ class HTTPClient(object):
51 64
     def token(self):
52 65
         if self.keystone is not None:
53 66
             try:
54
-                return self.keystone.auth_token
67
+                return self.session.get_token()
55 68
             except exceptions.AuthorizationFailure:
56 69
                 logger.warning(
57 70
                     'Cant establish connection to keystone with url %s',
@@ -60,37 +73,45 @@ class HTTPClient(object):
60 73
                 logger.warning("Keystone returned unauthorized error, trying "
61 74
                                "to pass authentication.")
62 75
                 self.authenticate()
63
-                return self.keystone.auth_token
76
+                return self.session.get_token()
64 77
         return None
65 78
 
66 79
     def get(self, endpoint):
67
-        req = urllib2.Request(self.url + endpoint)
80
+        req = request.Request(self.url + endpoint)
68 81
         return self._open(req)
69 82
 
70 83
     def post(self, endpoint, data=None, content_type="application/json"):
71 84
         if not data:
72 85
             data = {}
73
-        req = urllib2.Request(self.url + endpoint, data=json.dumps(data))
86
+        req = request.Request(self.url + endpoint, data=json.dumps(data))
74 87
         req.add_header('Content-Type', content_type)
75 88
         return self._open(req)
76 89
 
77 90
     def put(self, endpoint, data=None, content_type="application/json"):
78 91
         if not data:
79 92
             data = {}
80
-        req = urllib2.Request(self.url + endpoint, data=json.dumps(data))
93
+        req = request.Request(self.url + endpoint, data=json.dumps(data))
81 94
         req.add_header('Content-Type', content_type)
82 95
         req.get_method = lambda: 'PUT'
83 96
         return self._open(req)
84 97
 
85 98
     def delete(self, endpoint):
86
-        req = urllib2.Request(self.url + endpoint)
99
+        req = request.Request(self.url + endpoint)
87 100
         req.get_method = lambda: 'DELETE'
88 101
         return self._open(req)
89 102
 
90 103
     def _open(self, req):
91 104
         try:
92 105
             return self._get_response(req)
93
-        except urllib2.HTTPError as e:
106
+        except HTTPError as e:
107
+            if e.code == 308:
108
+                logger.info(e.read())
109
+                url = req.get_full_url()
110
+                req = requests.get(url, headers={'X-Auth-Token': self.token})
111
+                if req.status_code in [200]:
112
+                    return req.json()
113
+                else:
114
+                    req.raise_for_status()
94 115
             if e.code == 401:
95 116
                 logger.warning('Authorization failure: {0}'.format(e.read()))
96 117
                 self.authenticate()
@@ -121,10 +142,10 @@ class HTTPClientZabbix(object):
121 142
 
122 143
     def __init__(self, url):
123 144
         self.url = url
124
-        self.opener = urllib2.build_opener(urllib2.HTTPHandler)
145
+        self.opener = request.build_opener(request.HTTPHandler)
125 146
 
126 147
     def get(self, endpoint=None, cookie=None):
127
-        req = urllib2.Request(self.url + endpoint)
148
+        req = request.Request(self.url + endpoint)
128 149
         if cookie:
129 150
             req.add_header('cookie', cookie)
130 151
         return self.opener.open(req)
@@ -133,7 +154,7 @@ class HTTPClientZabbix(object):
133 154
              cookie=None):
134 155
         if not data:
135 156
             data = {}
136
-        req = urllib2.Request(self.url + endpoint, data=json.dumps(data))
157
+        req = request.Request(self.url + endpoint, data=json.dumps(data))
137 158
         req.add_header('Content-Type', content_type)
138 159
         if cookie:
139 160
             req.add_header('cookie', cookie)

+ 26
- 23
fuelweb_test/helpers/os_actions.py View File

@@ -12,13 +12,14 @@
12 12
 #    License for the specific language governing permissions and limitations
13 13
 #    under the License.
14 14
 
15
-import paramiko
16
-from proboscis import asserts
17 15
 import random
18 16
 import time
19 17
 
20 18
 from devops.error import TimeoutError
21 19
 from devops.helpers import helpers
20
+import paramiko
21
+from proboscis import asserts
22
+
22 23
 from fuelweb_test.helpers import common
23 24
 from fuelweb_test import logger
24 25
 
@@ -116,7 +117,7 @@ class OpenStackActions(common.Common):
116 117
                 " is {0}".format(self.get_instance_detail(srv).status))
117 118
 
118 119
     def create_server_for_migration(self, neutron=True, scenario='',
119
-                                    timeout=100, file=None, key_name=None,
120
+                                    timeout=100, filename=None, key_name=None,
120 121
                                     label=None, flavor=1, **kwargs):
121 122
         name = "test-serv" + str(random.randint(1, 0x7fffffff))
122 123
         security_group = {}
@@ -125,12 +126,12 @@ class OpenStackActions(common.Common):
125 126
                 with open(scenario, "r+") as f:
126 127
                     scenario = f.read()
127 128
         except Exception as exc:
128
-            logger.info("Error opening file: %s" % exc)
129
+            logger.info("Error opening file: {:s}".format(exc))
129 130
             raise Exception()
130 131
         image_id = self._get_cirros_image().id
131
-        security_group[self.keystone.tenant_id] =\
132
+        security_group[self.keystone_access.tenant_id] =\
132 133
             self.create_sec_group_for_ssh()
133
-        security_group = [security_group[self.keystone.tenant_id].name]
134
+        security_groups = [security_group[self.keystone_access.tenant_id].name]
134 135
 
135 136
         if neutron:
136 137
             net_label = label if label else 'net04'
@@ -138,15 +139,15 @@ class OpenStackActions(common.Common):
138 139
                        if net.label == net_label]
139 140
 
140 141
             kwargs.update({'nics': [{'net-id': network[0]}],
141
-                           'security_groups': security_group})
142
+                           'security_groups': security_groups})
142 143
         else:
143
-            kwargs.update({'security_groups': security_group})
144
+            kwargs.update({'security_groups': security_groups})
144 145
 
145 146
         srv = self.nova.servers.create(name=name,
146 147
                                        image=image_id,
147 148
                                        flavor=flavor,
148 149
                                        userdata=scenario,
149
-                                       files=file,
150
+                                       files=filename,
150 151
                                        key_name=key_name,
151 152
                                        **kwargs)
152 153
         try:
@@ -195,9 +196,8 @@ class OpenStackActions(common.Common):
195 196
             flip = self.neutron.create_floatingip(body)
196 197
             #   Wait active state for port
197 198
             port_id = flip['floatingip']['port_id']
198
-            helpers.wait(
199
-                lambda:
200
-                self.neutron.show_port(port_id)['port']['status'] == "ACTIVE")
199
+            helpers.wait(lambda: self.neutron.show_port(
200
+                port_id)['port']['status'] == "ACTIVE")
201 201
             return flip['floatingip']
202 202
 
203 203
         fl_ips_pool = self.nova.floating_ip_pools.list()
@@ -275,8 +275,9 @@ class OpenStackActions(common.Common):
275 275
         server = self.get_instance_detail(server.id)
276 276
         return server
277 277
 
278
-    def create_volume(self, size=1, image_id=None):
279
-        volume = self.cinder.volumes.create(size=size, imageRef=image_id)
278
+    def create_volume(self, size=1, image_id=None, **kwargs):
279
+        volume = self.cinder.volumes.create(size=size, imageRef=image_id,
280
+                                            **kwargs)
280 281
         helpers.wait(
281 282
             lambda: self.cinder.volumes.get(volume.id).status == "available",
282 283
             timeout=100)
@@ -308,18 +309,19 @@ class OpenStackActions(common.Common):
308 309
 
309 310
     def get_hosts_for_migr(self, srv_host_name):
310 311
         # Determine which host is available for live migration
311
-        host_list = filter(lambda host: host.host_name != srv_host_name,
312
-                           self.nova.hosts.list())
313
-        return filter(lambda host: host._info['service'] == 'compute',
314
-                      host_list)
312
+        return [
313
+            host for host in self.nova.hosts.list()
314
+            if host.host_name != srv_host_name and
315
+            host._info['service'] == 'compute']
315 316
 
316 317
     def get_md5sum(self, file_path, controller_ssh, vm_ip, creds=()):
317 318
         logger.info("Get file md5sum and compare it with previous one")
318 319
         out = self.execute_through_host(
319
-            controller_ssh, vm_ip, "md5sum %s" % file_path, creds)
320
+            controller_ssh, vm_ip, "md5sum {:s}".format(file_path), creds)
320 321
         return out['stdout']
321 322
 
322
-    def execute_through_host(self, ssh, vm_host, cmd, creds=()):
323
+    @staticmethod
324
+    def execute_through_host(ssh, vm_host, cmd, creds=()):
323 325
         logger.debug("Making intermediate transport")
324 326
         intermediate_transport = ssh._ssh.get_transport()
325 327
 
@@ -547,16 +549,17 @@ class OpenStackActions(common.Common):
547 549
     def get_vip(self, vip):
548 550
         return self.neutron.show_vip(vip)
549 551
 
550
-    def get_nova_instance_ip(self, srv, net_name='novanetwork', type='fixed'):
552
+    @staticmethod
553
+    def get_nova_instance_ip(srv, net_name='novanetwork', addrtype='fixed'):
551 554
         for network_label, address_list in srv.addresses.items():
552 555
             if network_label != net_name:
553 556
                 continue
554 557
             for addr in address_list:
555
-                if addr['OS-EXT-IPS:type'] == type:
558
+                if addr['OS-EXT-IPS:type'] == addrtype:
556 559
                     return addr['addr']
557 560
         raise Exception("Instance {0} doesn't have {1} address for network "
558 561
                         "{2}, available addresses: {3}".format(srv.id,
559
-                                                               type,
562
+                                                               addrtype,
560 563
                                                                net_name,
561 564
                                                                srv.addresses))
562 565
 

+ 16
- 11
fuelweb_test/requirements.txt View File

@@ -4,18 +4,23 @@ paramiko>=1.16.0  # LGPL
4 4
 proboscis==1.2.6.0
5 5
 ipaddr
6 6
 junitxml>=0.7.0
7
-netaddr
8
-pyOpenSSL>=0.14
9
-python-glanceclient>=0.18.0
10
-python-keystoneclient>=0.3.2
11
-python-novaclient>=2.15.0
12
-python-cinderclient>=1.0.5
13
-python-neutronclient>=2.6.0
14
-python-ironicclient>=0.8.0
15
-python-heatclient>=0.6.0
7
+netaddr>=0.7.12,!=0.7.16  # BSD
8
+pyOpenSSL>=0.14  # Apache-2.0
9
+Sphinx  # BSD  # Not required for tests, but required to build docs (pbr)
10
+docutils  # Not required for tests, but required to build docs (pbr)
11
+markupsafe  # Not required for tests, but required to build docs (pbr)
12
+pytz>=2013.6  # MIT  # Not required for tests, but required to build docs (pbr)
13
+keystoneauth1>=2.1.0  # Apache-2.0
14
+python-glanceclient>=1.2.0  # Apache-2.0
15
+python-keystoneclient>=1.6.0,!=1.8.0,!=2.1.0  # Apache-2.0
16
+python-novaclient>=2.29.0,!=2.33.0  # Apache-2.0
17
+python-cinderclient>=1.3.1  # Apache-2.0
18
+python-neutronclient>=2.6.0,!=4.1.0  # Apache-2.0
19
+python-ironicclient>=1.1.0  # Apache-2.0
20
+python-heatclient>=0.6.0  # Apache-2.0
16 21
 oslo.i18n>=3.1.0
17
-six
18
-Jinja2
22
+six>=1.9.0 # MIT
23
+Jinja2>=2.8  # BSD License (3 clause)
19 24
 AllPairs==2.0.1
20 25
 launchpadlib
21 26
 beautifulsoup4>=4.2.0

Loading…
Cancel
Save