# Copyright 2013, Big Switch Networks, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from __future__ import absolute_import
from collections import OrderedDict
from django.utils.translation import ugettext_lazy as _
from horizon import messages
from openstack_dashboard.api import neutron
neutronclient = neutron.neutronclient
[docs]class Vip(neutron.NeutronAPIDictWrapper):
"""Wrapper for neutron load balancer vip."""
def __init__(self, apiresource):
super(Vip, self).__init__(apiresource)
[docs]class Pool(neutron.NeutronAPIDictWrapper):
"""Wrapper for neutron load balancer pool."""
def __init__(self, apiresource):
if 'provider' not in apiresource:
apiresource['provider'] = None
apiresource['admin_state'] = \
'UP' if apiresource['admin_state_up'] else 'DOWN'
super(Pool, self).__init__(apiresource)
[docs]class Member(neutron.NeutronAPIDictWrapper):
"""Wrapper for neutron load balancer member."""
def __init__(self, apiresource):
apiresource['admin_state'] = \
'UP' if apiresource['admin_state_up'] else 'DOWN'
super(Member, self).__init__(apiresource)
[docs]class PoolStats(neutron.NeutronAPIDictWrapper):
"""Wrapper for neutron load balancer pool stats."""
def __init__(self, apiresource):
super(PoolStats, self).__init__(apiresource)
[docs]class PoolMonitor(neutron.NeutronAPIDictWrapper):
"""Wrapper for neutron load balancer pool health monitor."""
def __init__(self, apiresource):
apiresource['admin_state'] = \
'UP' if apiresource['admin_state_up'] else 'DOWN'
super(PoolMonitor, self).__init__(apiresource)
[docs]def vip_create(request, **kwargs):
"""Create a vip for a specified pool.
:param request: request context
:param address: virtual IP address
:param name: name for vip
:param description: description for vip
:param subnet_id: subnet_id for subnet of vip
:param protocol_port: transport layer port number for vip
:returns: Vip object
"""
body = {'vip': {'name': kwargs['name'],
'description': kwargs['description'],
'subnet_id': kwargs['subnet_id'],
'protocol_port': kwargs['protocol_port'],
'protocol': kwargs['protocol'],
'pool_id': kwargs['pool_id'],
'session_persistence': kwargs['session_persistence'],
'admin_state_up': kwargs['admin_state_up']
}}
if kwargs.get('connection_limit'):
body['vip']['connection_limit'] = kwargs['connection_limit']
if kwargs.get('address'):
body['vip']['address'] = kwargs['address']
vip = neutronclient(request).create_vip(body).get('vip')
return Vip(vip)
[docs]def vip_list(request, **kwargs):
vips = neutronclient(request).list_vips(**kwargs).get('vips')
return [Vip(v) for v in vips]
[docs]def vip_get(request, vip_id):
return _vip_get(request, vip_id, expand_resource=True)
def _vip_get(request, vip_id, expand_resource=False):
vip = neutronclient(request).show_vip(vip_id).get('vip')
if expand_resource:
vip['subnet'] = neutron.subnet_get(request, vip['subnet_id'])
vip['port'] = neutron.port_get(request, vip['port_id'])
vip['pool'] = _pool_get(request, vip['pool_id'])
return Vip(vip)
[docs]def vip_update(request, vip_id, **kwargs):
vip = neutronclient(request).update_vip(vip_id, kwargs).get('vip')
return Vip(vip)
[docs]def vip_delete(request, vip_id):
neutronclient(request).delete_vip(vip_id)
[docs]def pool_create(request, **kwargs):
"""Create a pool for specified protocol
:param request: request context
:param name: name for pool
:param description: description for pool
:param subnet_id: subnet_id for subnet of pool
:param protocol: load balanced protocol
:param lb_method: load balancer method
:param admin_state_up: admin state (default on)
"""
body = {'pool': {'name': kwargs['name'],
'description': kwargs['description'],
'subnet_id': kwargs['subnet_id'],
'protocol': kwargs['protocol'],
'lb_method': kwargs['lb_method'],
'admin_state_up': kwargs['admin_state_up'],
'provider': kwargs['provider'],
}}
pool = neutronclient(request).create_pool(body).get('pool')
return Pool(pool)
def _get_vip(request, pool, vip_dict):
if pool['vip_id'] is not None:
try:
if vip_dict:
vip = vip_dict.get(pool['vip_id'])
else:
vip = _vip_get(request, pool['vip_id'])
except Exception:
messages.warning(request, _("Unable to get VIP for pool "
"%(pool)s.") % {"pool": pool["id"]})
vip = Vip({'id': pool['vip_id'], 'name': ''})
return vip
else:
return None
[docs]def pool_list(request, **kwargs):
return _pool_list(request, expand_subnet=True, expand_vip=True, **kwargs)
def _pool_list(request, expand_subnet=False, expand_vip=False, **kwargs):
pools = neutronclient(request).list_pools(**kwargs).get('pools')
if expand_subnet:
subnets = neutron.subnet_list(request)
subnet_dict = OrderedDict((s.id, s) for s in subnets)
for p in pools:
p['subnet'] = subnet_dict.get(p['subnet_id'])
if expand_vip:
vips = vip_list(request)
vip_dict = OrderedDict((v.id, v) for v in vips)
for p in pools:
p['vip'] = _get_vip(request, p, vip_dict)
return [Pool(p) for p in pools]
[docs]def pool_get(request, pool_id):
return _pool_get(request, pool_id, expand_resource=True)
def _pool_get(request, pool_id, expand_resource=False):
try:
pool = neutronclient(request).show_pool(pool_id).get('pool')
except Exception:
messages.warning(request, _("Unable to get pool detail."))
return None
if expand_resource:
# TODO(lyj): The expand resource(subnet, member etc.) attached
# to a pool could be deleted without cleanup pool related database,
# this will cause exceptions if we trying to get the deleted resources.
# so we need to handle the situation by showing a warning message here.
# we can safely remove the try/except once the neutron bug is fixed
# https://bugs.launchpad.net/neutron/+bug/1406854
try:
pool['subnet'] = neutron.subnet_get(request, pool['subnet_id'])
except Exception:
messages.warning(request, _("Unable to get subnet for pool "
"%(pool)s.") % {"pool": pool_id})
pool['vip'] = _get_vip(request, pool, vip_dict=None)
# Check here to reduce the additional request if pool['members'] is
# empty
if pool['members']:
try:
pool['members'] = _member_list(request, expand_pool=False,
pool_id=pool_id)
except Exception:
messages.warning(request, _("Unable to get members for pool "
"%(pool)s.") % {"pool": pool_id})
# If the filter to get health monitors list is empty, all health
# monitors will be returned in the tenant.
if pool['health_monitors']:
monitors = []
for monitor_id in pool['health_monitors']:
try:
monitors.append(_pool_health_monitor_get(request,
monitor_id,
False))
except Exception:
messages.warning(request,
_("Unable to get health monitor "
"%(monitor_id)s for pool %(pool)s.")
% {"pool": pool_id,
"monitor_id": monitor_id})
pool['health_monitors'] = monitors
return Pool(pool)
[docs]def pool_update(request, pool_id, **kwargs):
pool = neutronclient(request).update_pool(pool_id, kwargs).get('pool')
return Pool(pool)
[docs]def pool_delete(request, pool):
neutronclient(request).delete_pool(pool)
# not linked to UI yet
[docs]def pool_stats(request, pool_id, **kwargs):
stats = neutronclient(request).retrieve_pool_stats(pool_id, **kwargs)
return PoolStats(stats)
[docs]def pool_health_monitor_create(request, **kwargs):
"""Create a health monitor
:param request: request context
:param type: type of monitor
:param delay: delay of monitor
:param timeout: timeout of monitor
:param max_retries: max retries [1..10]
:param http_method: http method
:param url_path: url path
:param expected_codes: http return code
:param admin_state_up: admin state
"""
monitor_type = kwargs['type'].upper()
body = {'health_monitor': {'type': monitor_type,
'delay': kwargs['delay'],
'timeout': kwargs['timeout'],
'max_retries': kwargs['max_retries'],
'admin_state_up': kwargs['admin_state_up']
}}
if monitor_type in ['HTTP', 'HTTPS']:
body['health_monitor']['http_method'] = kwargs['http_method']
body['health_monitor']['url_path'] = kwargs['url_path']
body['health_monitor']['expected_codes'] = kwargs['expected_codes']
mon = neutronclient(request).create_health_monitor(body).get(
'health_monitor')
return PoolMonitor(mon)
[docs]def pool_health_monitor_list(request, **kwargs):
monitors = neutronclient(request).list_health_monitors(
**kwargs).get('health_monitors')
return [PoolMonitor(m) for m in monitors]
[docs]def pool_health_monitor_get(request, monitor_id):
return _pool_health_monitor_get(request, monitor_id, expand_resource=True)
def _pool_health_monitor_get(request, monitor_id, expand_resource=False):
monitor = neutronclient(request
).show_health_monitor(monitor_id
).get('health_monitor')
if expand_resource:
pool_ids = [p['pool_id'] for p in monitor['pools']]
# If the filter to get pools list is empty, all pools will be
# returned in the tenant.
if pool_ids:
monitor['pools'] = _pool_list(request, id=pool_ids)
return PoolMonitor(monitor)
[docs]def pool_health_monitor_update(request, monitor_id, **kwargs):
monitor = neutronclient(request
).update_health_monitor(monitor_id, kwargs
).get('health_monitor')
return PoolMonitor(monitor)
[docs]def pool_health_monitor_delete(request, mon_id):
neutronclient(request).delete_health_monitor(mon_id)
[docs]def member_create(request, **kwargs):
"""Create a load balance member
:param request: request context
:param pool_id: pool_id of pool for member
:param address: IP address
:param protocol_port: transport layer port number
:param weight: weight for member
:param admin_state_up: admin_state
"""
body = {'member': {'pool_id': kwargs['pool_id'],
'address': kwargs['address'],
'protocol_port': kwargs['protocol_port'],
'admin_state_up': kwargs['admin_state_up']
}}
if kwargs.get('weight'):
body['member']['weight'] = kwargs['weight']
member = neutronclient(request).create_member(body).get('member')
return Member(member)
[docs]def member_list(request, **kwargs):
return _member_list(request, expand_pool=True, **kwargs)
def _member_list(request, expand_pool, **kwargs):
members = neutronclient(request).list_members(**kwargs).get('members')
if expand_pool:
pools = _pool_list(request)
pool_dict = OrderedDict((p.id, p) for p in pools)
for m in members:
m['pool_name'] = pool_dict.get(m['pool_id']).name_or_id
return [Member(m) for m in members]
[docs]def member_get(request, member_id):
return _member_get(request, member_id, expand_pool=True)
def _member_get(request, member_id, expand_pool):
member = neutronclient(request).show_member(member_id).get('member')
if expand_pool:
member['pool'] = _pool_get(request, member['pool_id'])
return Member(member)
[docs]def member_update(request, member_id, **kwargs):
member = neutronclient(request).update_member(member_id, kwargs
).get('member')
return Member(member)
[docs]def member_delete(request, mem_id):
neutronclient(request).delete_member(mem_id)
[docs]def pool_monitor_association_create(request, **kwargs):
"""Associate a health monitor with pool
:param request: request context
:param monitor_id: id of monitor
:param pool_id: id of pool
"""
body = {'health_monitor': {'id': kwargs['monitor_id'], }}
neutronclient(request).associate_health_monitor(
kwargs['pool_id'], body)
[docs]def pool_monitor_association_delete(request, **kwargs):
"""Disassociate a health monitor from pool
:param request: request context
:param monitor_id: id of monitor
:param pool_id: id of pool
"""
neutronclient(request).disassociate_health_monitor(
kwargs['pool_id'], kwargs['monitor_id'])