Skip to content

Commit

Permalink
Proper port for LBaaS members
Browse files Browse the repository at this point in the history
This patch set makes loadbalancer select a port on pool subnet
for new members if possible.

Conflicts:
        openstack_dashboard/dashboards/project/loadbalancers/tests.py
        openstack_dashboard/dashboards/project/loadbalancers/workflows.py

Closes-Bug: #1288859

Change-Id: I0809908ec5d15a448691dccf526b66308cf929d4
(cherry picked from commit 98bd315)
  • Loading branch information
Tatiana Mazur authored and xtmprsqzntwlfb committed Aug 5, 2014
1 parent 2b9c566 commit 95dcdae
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 13 deletions.
30 changes: 24 additions & 6 deletions openstack_dashboard/dashboards/project/loadbalancers/tests.py
Expand Up @@ -453,10 +453,13 @@ def test_add_member_post(self):
def test_add_member_post_without_weight(self):
self._test_add_member_post(with_weight=False)

@test.create_stubs({api.lbaas: ('pool_list', 'member_create'),
def test_add_member_post_multiple_ports(self):
self._test_add_member_post(mult_ports=True)

@test.create_stubs({api.lbaas: ('pool_list', 'pool_get', 'member_create'),
api.neutron: ('port_list',),
api.nova: ('server_list',)})
def _test_add_member_post(self, with_weight=True):
def _test_add_member_post(self, with_weight=True, mult_ports=False):
member = self.members.first()

server1 = self.AttributeDict({'id':
Expand All @@ -465,18 +468,33 @@ def _test_add_member_post(self, with_weight=True):
server2 = self.AttributeDict({'id':
'12381d38-c3eb-4fee-9763-12de3338043e',
'name': 'vm2'})

pool = self.pools.list()[1]
port1 = self.AttributeDict(
{'fixed_ips': [{'ip_address': member.address}]})
{'fixed_ips': [{'ip_address': member.address,
'subnet_id':
'e8abc972-eb0c-41f1-9edd-4bc6e3bcd8c9'}],
'network_id': '82288d84-e0a5-42ac-95be-e6af08727e42'})

api.lbaas.pool_list(IsA(http.HttpRequest), tenant_id=self.tenant.id) \
.AndReturn(self.pools.list())

api.nova.server_list(IsA(http.HttpRequest)).AndReturn(
[[server1, server2], False])

api.neutron.port_list(IsA(http.HttpRequest),
device_id=server1.id).AndReturn([port1, ])
api.lbaas.pool_get(
IsA(http.HttpRequest), pool.id).AndReturn(pool)

if mult_ports:
port2 = self.AttributeDict(
{'fixed_ips': [{'ip_address': '172.16.88.12',
'subnet_id':
'3f7c5d79-ee55-47b0-9213-8e669fb03009'}],
'network_id': '72c3ab6c-c80f-4341-9dc5-210fa31ac6c2'})
api.neutron.port_list(IsA(http.HttpRequest),
device_id=server1.id).AndReturn([port1, port2])
else:
api.neutron.port_list(IsA(http.HttpRequest),
device_id=server1.id).AndReturn([port1, ])

params = {'pool_id': member.pool_id,
'address': member.address,
Expand Down
44 changes: 37 additions & 7 deletions openstack_dashboard/dashboards/project/loadbalancers/workflows.py
Expand Up @@ -14,6 +14,8 @@
# License for the specific language governing permissions and limitations
# under the License.

import logging

from django.utils.translation import ugettext_lazy as _

from horizon import exceptions
Expand All @@ -29,6 +31,9 @@
AVAILABLE_METHODS = ('ROUND_ROBIN', 'LEAST_CONNECTIONS', 'SOURCE_IP')


LOG = logging.getLogger(__name__)


class AddPoolAction(workflows.Action):
name = forms.CharField(max_length=80, label=_("Name"))
description = forms.CharField(
Expand Down Expand Up @@ -387,19 +392,44 @@ class AddMember(workflows.Workflow):
default_steps = (AddMemberStep,)

def handle(self, request, context):
try:
pool = api.lbaas.pool_get(request, context['pool_id'])
subnet_id = pool['subnet_id']
except Exception:
self.failure_message = _('Unable to retrieve '
'the specified pool.')
return False
for m in context['members']:
params = {'device_id': m}
try:
plist = api.neutron.port_list(request, **params)
except Exception:
return False
if plist:
context['address'] = plist[0].fixed_ips[0]['ip_address']
try:
context['member_id'] = api.lbaas.member_create(
request, **context).id
except Exception:
return False

# Sort port list for each member. This is needed to avoid
# attachment of random ports in case of creation of several
# members attached to several networks.
plist = sorted(plist, key=lambda port: port.network_id)
psubnet = [p for p in plist for ips in p.fixed_ips
if ips['subnet_id'] == subnet_id]

# If possible, select a port on pool subnet.
if psubnet:
selected_port = psubnet[0]
elif plist:
selected_port = plist[0]
else:
selected_port = None

if selected_port:
context['address'] = \
selected_port.fixed_ips[0]['ip_address']
try:
api.lbaas.member_create(request, **context).id
except Exception as e:
msg = self.failure_message
LOG.info('%s: %s' % (msg, e))
return False
return True


Expand Down

0 comments on commit 95dcdae

Please sign in to comment.