Skip to content

Commit 4413f46

Browse files
ankur-odljohnsom
andcommitted
Update load_balancer for v2 API
This patch updates the load_balancer.v2.load_balancer for the current state of the API It also updates the post_test_hook script to accept an argument to restrict the functional tests run. Since the load-balancer tests can take a significant time to run, this allows us to run a parallel gate job for the load-balancer functional tests. Co-Authored-By: Michael Johnson <[email protected]> Change-Id: I6c526cd8225a929d3d5984da10b6478312461e6f
1 parent a71579f commit 4413f46

File tree

17 files changed

+197
-38
lines changed

17 files changed

+197
-38
lines changed

doc/source/enforcer.py

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def get_proxy_methods():
3636
"openstack.image.v1._proxy",
3737
"openstack.image.v2._proxy",
3838
"openstack.key_manager.v1._proxy",
39+
"openstack.load_balancer.v2._proxy",
3940
"openstack.message.v1._proxy",
4041
"openstack.message.v2._proxy",
4142
"openstack.metric.v1._proxy",

doc/source/users/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ The following services have exposed *Resource* classes.
114114
Identity <resources/identity/index>
115115
Image <resources/image/index>
116116
Key Management <resources/key_manager/index>
117+
Load Balancer <resources/load_balancer/index>
117118
Metric <resources/metric/index>
118119
Network <resources/network/index>
119120
Orchestration <resources/orchestration/index>

doc/source/users/proxies/load_balancer_v2.rst

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ Load Balancer Operations
1616
.. autoclass:: openstack.load_balancer.v2._proxy.Proxy
1717

1818
.. automethod:: openstack.load_balancer.v2._proxy.Proxy.create_load_balancer
19-
.. automethod:: openstack.load_balancer.v2._proxy.Proxy.get_load_balancer
20-
.. automethod:: openstack.load_balancer.v2._proxy.Proxy.load_balancers
2119
.. automethod:: openstack.load_balancer.v2._proxy.Proxy.delete_load_balancer
2220
.. automethod:: openstack.load_balancer.v2._proxy.Proxy.find_load_balancer
21+
.. automethod:: openstack.load_balancer.v2._proxy.Proxy.get_load_balancer
22+
.. automethod:: openstack.load_balancer.v2._proxy.Proxy.load_balancers
23+
.. automethod:: openstack.load_balancer.v2._proxy.Proxy.update_load_balancer
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Load Balancer Resources
2+
=======================
3+
4+
.. toctree::
5+
:maxdepth: 1
6+
7+
v2/load_balancer
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
openstack.load_balancer.v2.load_balancer
2+
========================================
3+
4+
.. automodule:: openstack.load_balancer.v2.load_balancer
5+
6+
The LoadBalancer Class
7+
----------------------
8+
9+
The ``LoadBalancer`` class inherits from :class:`~openstack.resource.Resource`.
10+
11+
.. autoclass:: openstack.load_balancer.v2.load_balancer.LoadBalancer
12+
:members:
13+

openstack/load_balancer/load_balancer_service.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616
class LoadBalancerService(service_filter.ServiceFilter):
1717
"""The load balancer service."""
1818

19-
valid_versions = [service_filter.ValidVersion('v2')]
19+
valid_versions = [service_filter.ValidVersion('v2', 'v2.0')]
2020

2121
def __init__(self, version=None):
2222
"""Create a load balancer service."""
2323
super(LoadBalancerService, self).__init__(
24-
service_type='load_balancer',
24+
service_type='load-balancer',
2525
version=version
2626
)

openstack/load_balancer/v2/_proxy.py

+14
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,17 @@ def find_load_balancer(self, name_or_id, ignore_missing=True):
8080
"""
8181
return self._find(_lb.LoadBalancer, name_or_id,
8282
ignore_missing=ignore_missing)
83+
84+
def update_load_balancer(self, load_balancer, **attrs):
85+
"""Update a load balancer
86+
87+
:param load_balancer: The load_balancer can be either the name or a
88+
:class:`~openstack.load_balancer.v2.load_balancer.LoadBalancer`
89+
instance
90+
:param dict attrs: The attributes to update on the load balancer
91+
represented by ``load_balancer``.
92+
93+
:returns: The updated load_balancer
94+
:rtype: :class:`~openstack.load_balancer.v2.load_balancer.LoadBalancer`
95+
"""
96+
return self._update(_lb.LoadBalancer, load_balancer, **attrs)

openstack/load_balancer/v2/load_balancer.py

+19-6
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,31 @@
1717
class LoadBalancer(resource.Resource):
1818
resource_key = 'loadbalancer'
1919
resources_key = 'loadbalancers'
20-
base_path = '/loadbalancers'
20+
base_path = '/v2.0/lbaas/loadbalancers'
2121
service = lb_service.LoadBalancerService()
2222

2323
# capabilities
2424
allow_create = True
25-
allow_list = True
2625
allow_get = True
26+
allow_update = True
2727
allow_delete = True
28+
allow_list = True
29+
30+
_query_mapping = resource.QueryParameters(
31+
'description', 'flavor', 'name', 'project_id', 'provider',
32+
'vip_address', 'vip_network_id', 'vip_port_id', 'vip_subnet_id',
33+
is_admin_state_up='admin_state_up'
34+
)
2835

2936
#: Properties
37+
#: The administrative state of the load balancer *Type: bool*
38+
is_admin_state_up = resource.Body('admin_state_up', type=bool)
3039
#: Timestamp when the load balancer was created
3140
created_at = resource.Body('created_at')
3241
#: The load balancer description
3342
description = resource.Body('description')
34-
#: The administrative state of the load balancer *Type: bool*
35-
is_admin_state_up = resource.Body('admin_state_up', type=bool)
43+
#: The load balancer flavor
44+
flavor = resource.Body('flavor')
3645
#: List of listeners associated with this load balancer
3746
listeners = resource.Body('listeners', type=list)
3847
#: The load balancer name
@@ -43,13 +52,17 @@ class LoadBalancer(resource.Resource):
4352
pools = resource.Body('pools', type=list)
4453
#: The ID of the project this load balancer is associated with.
4554
project_id = resource.Body('project_id')
55+
#: Provider name for the load balancer.
56+
provider = resource.Body('provider')
4657
#: The provisioning status of this load balancer
4758
provisioning_status = resource.Body('provisioning_status')
59+
#: Timestamp when the load balancer was last updated
60+
updated_at = resource.Body('updated_at')
4861
#: VIP address of load balancer
4962
vip_address = resource.Body('vip_address')
63+
#: VIP netowrk ID
64+
vip_network_id = resource.Body('vip_network_id')
5065
#: VIP port ID
5166
vip_port_id = resource.Body('vip_port_id')
5267
#: VIP subnet ID
5368
vip_subnet_id = resource.Body('vip_subnet_id')
54-
#: Timestamp when the load balancer was last updated
55-
updated_at = resource.Body('updated_at')

openstack/session.py

+5
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,11 @@ def get_endpoint(self, auth=None, interface=None, service_type=None,
330330
self.endpoint_cache[key] = sc_endpoint
331331
return sc_endpoint
332332

333+
# We just want what is returned from catalog
334+
if service_type == "load-balancer":
335+
self.endpoint_cache[key] = sc_endpoint
336+
return sc_endpoint
337+
333338
endpoint = self._get_endpoint_versions(service_type, sc_endpoint)
334339

335340
profile_version = self._parse_version(filt.version)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Copyright 2017 Rackspace, US Inc.
2+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
3+
# not use this file except in compliance with the License. You may obtain
4+
# 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, WITHOUT
10+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11+
# License for the specific language governing permissions and limitations
12+
# under the License.
13+
14+
import time
15+
16+
from openstack import exceptions
17+
from openstack.tests.functional import base
18+
19+
20+
class BaseLBFunctionalTest(base.BaseFunctionalTest):
21+
22+
@classmethod
23+
def setUpClass(cls):
24+
super(BaseLBFunctionalTest, cls).setUpClass()
25+
26+
@classmethod
27+
def lb_wait_for_status(cls, lb, status, failures, interval=1, wait=120):
28+
"""Wait for load balancer to be in a particular provisioning status.
29+
30+
:param lb: The load balancer to wait on to reach the status.
31+
:type lb: :class:`~openstack.load_blanacer.v2.load_balancer
32+
:param status: Desired status of the resource.
33+
:param list failures: Statuses that would indicate the transition
34+
failed such as 'ERROR'.
35+
:param interval: Number of seconds to wait between checks.
36+
:param wait: Maximum number of seconds to wait for transition.
37+
Note, most actions should easily finish in 120 seconds,
38+
but for load balancer create slow hosts can take up to
39+
ten minutes for nova to fully boot a VM.
40+
:return: None
41+
:raises: :class:`~openstack.exceptions.ResourceTimeout` transition
42+
to status failed to occur in wait seconds.
43+
:raises: :class:`~openstack.exceptions.ResourceFailure` resource
44+
transitioned to one of the failure states.
45+
"""
46+
47+
total_sleep = 0
48+
if failures is None:
49+
failures = []
50+
51+
while total_sleep < wait:
52+
lb = cls.conn.load_balancer.get_load_balancer(lb.id)
53+
if lb.provisioning_status == status:
54+
return None
55+
if lb.provisioning_status in failures:
56+
msg = ("Load Balancer %s transitioned to failure state %s" %
57+
(lb.id, lb.provisioning_status))
58+
raise exceptions.ResourceFailure(msg)
59+
time.sleep(interval)
60+
total_sleep += interval
61+
msg = "Timeout waiting for Load Balancer %s to transition to %s" % (
62+
lb.id, status)
63+
raise exceptions.ResourceTimeout(msg)

openstack/tests/functional/load_balancer/v2/test_load_balancer.py

+28-7
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,43 @@
1515

1616
from openstack.load_balancer.v2 import load_balancer
1717
from openstack.tests.functional import base
18+
from openstack.tests.functional.load_balancer import base as lb_base
1819

1920

20-
@unittest.skipUnless(base.service_exists(service_type='load_balancer'),
21-
'Load-balancing service does not exist')
22-
class TestLoadBalancer(base.BaseFunctionalTest):
21+
@unittest.skipUnless(base.service_exists(service_type='load-balancer'),
22+
'Load-balancer service does not exist')
23+
class TestLoadBalancer(lb_base.BaseLBFunctionalTest):
2324

2425
NAME = uuid.uuid4().hex
2526
ID = None
26-
VIP_SUBNET_ID = uuid.uuid4().hex
27+
VIP_SUBNET_ID = None
28+
PROJECT_ID = None
29+
UPDATE_NAME = uuid.uuid4().hex
2730

2831
@classmethod
2932
def setUpClass(cls):
3033
super(TestLoadBalancer, cls).setUpClass()
34+
subnets = list(cls.conn.network.subnets())
35+
cls.VIP_SUBNET_ID = subnets[0].id
36+
cls.PROJECT_ID = cls.conn.session.get_project_id()
3137
test_lb = cls.conn.load_balancer.create_load_balancer(
32-
name=cls.NAME, vip_subnet_id=cls.VIP_SUBNET_ID)
38+
name=cls.NAME, vip_subnet_id=cls.VIP_SUBNET_ID,
39+
project_id=cls.PROJECT_ID)
3340
assert isinstance(test_lb, load_balancer.LoadBalancer)
3441
cls.assertIs(cls.NAME, test_lb.name)
42+
# Wait for the LB to go ACTIVE. On non-virtualization enabled hosts
43+
# it can take nova up to ten minutes to boot a VM.
44+
cls.lb_wait_for_status(test_lb, status='ACTIVE',
45+
failures=['ERROR'], interval=1, wait=600)
3546
cls.ID = test_lb.id
3647

3748
@classmethod
3849
def tearDownClass(cls):
39-
test_lb = cls.conn.load_balancer.delete_load_balancer(
50+
test_lb = cls.conn.load_balancer.get_load_balancer(cls.ID)
51+
cls.lb_wait_for_status(test_lb, status='ACTIVE',
52+
failures=['ERROR'])
53+
cls.conn.load_balancer.delete_load_balancer(
4054
cls.ID, ignore_missing=False)
41-
cls.assertIs(None, test_lb)
4255

4356
def test_find(self):
4457
test_lb = self.conn.load_balancer.find_load_balancer(self.NAME)
@@ -53,3 +66,11 @@ def test_get(self):
5366
def test_list(self):
5467
names = [lb.name for lb in self.conn.load_balancer.load_balancers()]
5568
self.assertIn(self.NAME, names)
69+
70+
def test_update(self):
71+
update_lb = self.conn.load_balancer.update_load_balancer(
72+
self.ID, name=self.UPDATE_NAME)
73+
self.lb_wait_for_status(update_lb, status='ACTIVE',
74+
failures=['ERROR'])
75+
test_lb = self.conn.load_balancer.get_load_balancer(self.ID)
76+
self.assertEqual(self.UPDATE_NAME, test_lb.name)

openstack/tests/unit/load_balancer/test_load_balancer.py

+27-15
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,29 @@
1111
# under the License.
1212

1313
import testtools
14+
import uuid
1415

1516
from openstack.load_balancer.v2 import load_balancer
1617

1718
IDENTIFIER = 'IDENTIFIER'
1819
EXAMPLE = {
1920
'admin_state_up': True,
20-
'created_at': '3',
21+
'created_at': '2017-07-17T12:14:57.233772',
2122
'description': 'fake_description',
23+
'flavor': uuid.uuid4(),
2224
'id': IDENTIFIER,
23-
'listeners': [{'id', '4'}],
25+
'listeners': [{'id', uuid.uuid4()}],
2426
'name': 'test_load_balancer',
25-
'operating_status': '6',
26-
'provisioning_status': '7',
27-
'project_id': '8',
28-
'vip_address': '9',
29-
'vip_subnet_id': '10',
30-
'vip_port_id': '11',
31-
'pools': [{'id', '13'}],
27+
'operating_status': 'ONLINE',
28+
'pools': [{'id', uuid.uuid4()}],
29+
'project_id': uuid.uuid4(),
30+
'provider': 'fake_provider',
31+
'provisioning_status': 'ACTIVE',
32+
'updated_at': '2017-07-17T12:16:57.233772',
33+
'vip_address': '192.0.2.5',
34+
'vip_network_id': uuid.uuid4(),
35+
'vip_port_id': uuid.uuid4(),
36+
'vip_subnet_id': uuid.uuid4(),
3237
}
3338

3439

@@ -38,32 +43,39 @@ def test_basic(self):
3843
test_load_balancer = load_balancer.LoadBalancer()
3944
self.assertEqual('loadbalancer', test_load_balancer.resource_key)
4045
self.assertEqual('loadbalancers', test_load_balancer.resources_key)
41-
self.assertEqual('/loadbalancers', test_load_balancer.base_path)
42-
self.assertEqual('load_balancer',
46+
self.assertEqual('/v2.0/lbaas/loadbalancers',
47+
test_load_balancer.base_path)
48+
self.assertEqual('load-balancer',
4349
test_load_balancer.service.service_type)
4450
self.assertTrue(test_load_balancer.allow_create)
4551
self.assertTrue(test_load_balancer.allow_get)
4652
self.assertTrue(test_load_balancer.allow_delete)
4753
self.assertTrue(test_load_balancer.allow_list)
54+
self.assertTrue(test_load_balancer.allow_update)
4855

4956
def test_make_it(self):
5057
test_load_balancer = load_balancer.LoadBalancer(**EXAMPLE)
5158
self.assertTrue(test_load_balancer.is_admin_state_up)
5259
self.assertEqual(EXAMPLE['created_at'], test_load_balancer.created_at),
5360
self.assertEqual(EXAMPLE['description'],
5461
test_load_balancer.description)
62+
self.assertEqual(EXAMPLE['flavor'], test_load_balancer.flavor)
5563
self.assertEqual(EXAMPLE['id'], test_load_balancer.id)
5664
self.assertEqual(EXAMPLE['listeners'], test_load_balancer.listeners)
5765
self.assertEqual(EXAMPLE['name'], test_load_balancer.name)
5866
self.assertEqual(EXAMPLE['operating_status'],
5967
test_load_balancer.operating_status)
68+
self.assertEqual(EXAMPLE['pools'], test_load_balancer.pools)
69+
self.assertEqual(EXAMPLE['project_id'], test_load_balancer.project_id)
70+
self.assertEqual(EXAMPLE['provider'], test_load_balancer.provider)
6071
self.assertEqual(EXAMPLE['provisioning_status'],
6172
test_load_balancer.provisioning_status)
62-
self.assertEqual(EXAMPLE['project_id'], test_load_balancer.project_id)
73+
self.assertEqual(EXAMPLE['updated_at'], test_load_balancer.updated_at),
6374
self.assertEqual(EXAMPLE['vip_address'],
6475
test_load_balancer.vip_address)
65-
self.assertEqual(EXAMPLE['vip_subnet_id'],
66-
test_load_balancer.vip_subnet_id)
76+
self.assertEqual(EXAMPLE['vip_network_id'],
77+
test_load_balancer.vip_network_id)
6778
self.assertEqual(EXAMPLE['vip_port_id'],
6879
test_load_balancer.vip_port_id)
69-
self.assertEqual(EXAMPLE['pools'], test_load_balancer.pools)
80+
self.assertEqual(EXAMPLE['vip_subnet_id'],
81+
test_load_balancer.vip_subnet_id)

openstack/tests/unit/load_balancer/test_load_balancer_service.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ class TestLoadBalancingService(testtools.TestCase):
1919

2020
def test_service(self):
2121
sot = lb_service.LoadBalancerService()
22-
self.assertEqual('load_balancer', sot.service_type)
22+
self.assertEqual('load-balancer', sot.service_type)
2323
self.assertEqual('public', sot.interface)
2424
self.assertIsNone(sot.region)
2525
self.assertIsNone(sot.service_name)
2626
self.assertEqual(1, len(sot.valid_versions))
2727
self.assertEqual('v2', sot.valid_versions[0].module)
28-
self.assertEqual('v2', sot.valid_versions[0].path)
28+
self.assertEqual('v2.0', sot.valid_versions[0].path)

openstack/tests/unit/load_balancer/test_proxy.py

+4
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,7 @@ def test_load_balancer_delete(self):
4040
def test_load_balancer_find(self):
4141
self.verify_find(self.proxy.find_load_balancer,
4242
lb.LoadBalancer)
43+
44+
def test_load_balancer_update(self):
45+
self.verify_update(self.proxy.update_load_balancer,
46+
lb.LoadBalancer)

openstack/tests/unit/load_balancer/test_version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def test_basic(self):
2929
self.assertEqual('version', sot.resource_key)
3030
self.assertEqual('versions', sot.resources_key)
3131
self.assertEqual('/', sot.base_path)
32-
self.assertEqual('load_balancer', sot.service.service_type)
32+
self.assertEqual('load-balancer', sot.service.service_type)
3333
self.assertFalse(sot.allow_create)
3434
self.assertFalse(sot.allow_get)
3535
self.assertFalse(sot.allow_update)

0 commit comments

Comments
 (0)