Drop LBaaS v1 dashboard

LBaaS v1 feature was removed from neutron-lbaas in Newton.
There is no reason we have LBaaS v1 dashboard in Ocata or later.

Change-Id: Ic7d4ceea1943c3721500ce4b7f769b9dba28a359
Closes-Bug: #1624655
This commit is contained in:
Akihiro Motoki 2016-09-17 19:54:27 +09:00
parent dd66682da7
commit 7e64a1cef1
41 changed files with 11 additions and 4748 deletions

View File

@ -1196,7 +1196,6 @@ Default::
'enable_router': True,
'enable_distributed_router': False,
'enable_ha_router': False,
'enable_lb': True,
'enable_quotas': False,
'enable_firewall': True,
'enable_vpn': True,
@ -1253,24 +1252,6 @@ Even when your Neutron plugin (like ML2 plugin) supports HA router mode,
the feature depends on l3-agent configuration, so deployers should set this
option appropriately depending on your deployment.
``enable_lb``
~~~~~~~~~~~~~
.. versionadded:: 2013.1(Grizzly)
(Deprecated)
Default: ``True``
Enables the load balancer panel. The load balancer panel will be enabled when
this option is True and your Neutron deployment supports LBaaS. If you want
to disable load balancer panel even when your Neutron supports LBaaS, set it to False.
This option is now marked as "deprecated" and will be removed in Kilo or later release.
The load balancer panel is now enabled only when LBaaS feature is available in Neutron
and this option is no longer needed. We suggest not to use this option to disable the
load balancer panel from now on.
``enable_quotas``
~~~~~~~~~~~~~~~~~

View File

@ -38,7 +38,6 @@ from openstack_dashboard.api import fwaas
from openstack_dashboard.api import glance
from openstack_dashboard.api import heat
from openstack_dashboard.api import keystone
from openstack_dashboard.api import lbaas
from openstack_dashboard.api import network
from openstack_dashboard.api import neutron
from openstack_dashboard.api import nova
@ -53,7 +52,6 @@ __all__ = [
"glance",
"heat",
"keystone",
"lbaas",
"network",
"neutron",
"nova",

View File

@ -1,394 +0,0 @@
# 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
class Vip(neutron.NeutronAPIDictWrapper):
"""Wrapper for neutron load balancer vip."""
def __init__(self, apiresource):
super(Vip, self).__init__(apiresource)
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)
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)
class PoolStats(neutron.NeutronAPIDictWrapper):
"""Wrapper for neutron load balancer pool stats."""
def __init__(self, apiresource):
super(PoolStats, self).__init__(apiresource)
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)
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)
def vip_list(request, **kwargs):
vips = neutronclient(request).list_vips(**kwargs).get('vips')
return [Vip(v) for v in vips]
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)
def vip_update(request, vip_id, **kwargs):
vip = neutronclient(request).update_vip(vip_id, kwargs).get('vip')
return Vip(vip)
def vip_delete(request, vip_id):
neutronclient(request).delete_vip(vip_id)
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
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]
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)
def pool_update(request, pool_id, **kwargs):
pool = neutronclient(request).update_pool(pool_id, kwargs).get('pool')
return Pool(pool)
def pool_delete(request, pool):
neutronclient(request).delete_pool(pool)
# not linked to UI yet
def pool_stats(request, pool_id, **kwargs):
stats = neutronclient(request).retrieve_pool_stats(pool_id, **kwargs)
return PoolStats(stats)
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)
def pool_health_monitor_list(request, **kwargs):
monitors = neutronclient(request).list_health_monitors(
**kwargs).get('health_monitors')
return [PoolMonitor(m) for m in monitors]
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)
def pool_health_monitor_update(request, monitor_id, **kwargs):
monitor = neutronclient(request
).update_health_monitor(monitor_id, kwargs
).get('health_monitor')
return PoolMonitor(monitor)
def pool_health_monitor_delete(request, mon_id):
neutronclient(request).delete_health_monitor(mon_id)
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)
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]
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)
def member_update(request, member_id, **kwargs):
member = neutronclient(request).update_member(member_id, kwargs
).get('member')
return Member(member)
def member_delete(request, mem_id):
neutronclient(request).delete_member(mem_id)
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)
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'])

View File

@ -476,14 +476,6 @@ class FloatingIpManager(network_base.FloatingIpManager):
server_dict = collections.OrderedDict(
[(s.id, s.name) for s in servers])
reachable_subnets = self._get_reachable_subnets(ports)
if is_service_enabled(self.request,
config_name='enable_lb',
ext_name='lbaas'):
# Also get the loadbalancer VIPs
vip_dict = {v['port_id']: v['name']
for v in self.client.list_vips().get('vips', [])}
else:
vip_dict = {}
targets = []
for p in ports:
@ -491,7 +483,7 @@ class FloatingIpManager(network_base.FloatingIpManager):
if p.device_owner.startswith('network:'):
continue
port_id = p.id
server_name = server_dict.get(p.device_id) or vip_dict.get(port_id)
server_name = server_dict.get(p.device_id)
for ip in p.fixed_ips:
if ip['subnet_id'] not in reachable_subnets:

View File

@ -1,281 +0,0 @@
# Copyright 2013, Mirantis 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.
import logging
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
from horizon import messages
from openstack_dashboard import api
LOG = logging.getLogger(__name__)
class UpdatePool(forms.SelfHandlingForm):
name = forms.CharField(max_length=80, label=_("Name"))
pool_id = forms.CharField(label=_("ID"),
widget=forms.TextInput(
attrs={'readonly': 'readonly'}))
description = forms.CharField(required=False,
max_length=80, label=_("Description"))
lb_method = forms.ThemableChoiceField(label=_("Load Balancing Method"))
admin_state_up = forms.ThemableChoiceField(
choices=[(True, _('UP')),
(False, _('DOWN'))],
label=_("Admin State"))
failure_url = 'horizon:project:loadbalancers:index'
def __init__(self, request, *args, **kwargs):
super(UpdatePool, self).__init__(request, *args, **kwargs)
lb_method_choices = [('ROUND_ROBIN', 'ROUND_ROBIN'),
('LEAST_CONNECTIONS', 'LEAST_CONNECTIONS'),
('SOURCE_IP', 'SOURCE_IP')]
self.fields['lb_method'].choices = lb_method_choices
def handle(self, request, context):
context['admin_state_up'] = (context['admin_state_up'] == 'True')
try:
data = {'pool': {'name': context['name'],
'description': context['description'],
'lb_method': context['lb_method'],
'admin_state_up': context['admin_state_up'],
}}
pool = api.lbaas.pool_update(request, context['pool_id'], **data)
msg = _('Pool %s was successfully updated.') % context['name']
LOG.debug(msg)
messages.success(request, msg)
return pool
except Exception:
msg = _('Failed to update pool %s') % context['name']
LOG.info(msg)
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)
class UpdateVip(forms.SelfHandlingForm):
name = forms.CharField(max_length=80, label=_("Name"))
vip_id = forms.CharField(label=_("ID"),
widget=forms.TextInput(
attrs={'readonly': 'readonly'}))
description = forms.CharField(required=False,
max_length=80, label=_("Description"))
pool_id = forms.ThemableChoiceField(label=_("Pool"))
session_persistence = forms.ThemableChoiceField(
required=False, initial={}, label=_("Session Persistence"))
cookie_name = forms.CharField(
initial="", required=False,
max_length=80, label=_("Cookie Name"),
help_text=_("Required for APP_COOKIE persistence;"
" Ignored otherwise."))
connection_limit = forms.IntegerField(
min_value=-1, label=_("Connection Limit"),
help_text=_("Maximum number of connections allowed "
"for the VIP or '-1' if the limit is not set"))
admin_state_up = forms.ThemableChoiceField(
choices=[(True, _('UP')),
(False, _('DOWN'))],
label=_("Admin State"))
failure_url = 'horizon:project:loadbalancers:index'
def __init__(self, request, *args, **kwargs):
super(UpdateVip, self).__init__(request, *args, **kwargs)
pool_id_choices = []
try:
tenant_id = request.user.tenant_id
pools = api.lbaas.pool_list(request, tenant_id=tenant_id)
except Exception:
pools = []
exceptions.handle(request,
_('Unable to retrieve pools list.'))
pools = sorted(pools,
key=lambda pool: pool.name)
for p in pools:
if (p.vip_id is None) or (p.id == kwargs['initial']['pool_id']):
pool_id_choices.append((p.id, p.name))
self.fields['pool_id'].choices = pool_id_choices
session_persistence_choices = []
for mode in ('SOURCE_IP', 'HTTP_COOKIE', 'APP_COOKIE'):
session_persistence_choices.append((mode, mode))
session_persistence_choices.append(('', _('No session persistence')))
self.fields[
'session_persistence'].choices = session_persistence_choices
def clean(self):
cleaned_data = super(UpdateVip, self).clean()
persistence = cleaned_data.get('session_persistence')
if (persistence == 'APP_COOKIE' and
not cleaned_data.get('cookie_name')):
msg = _('Cookie name is required for APP_COOKIE persistence.')
self._errors['cookie_name'] = self.error_class([msg])
return cleaned_data
def handle(self, request, context):
context['admin_state_up'] = (context['admin_state_up'] == 'True')
if context['session_persistence']:
stype = context['session_persistence']
if stype == 'APP_COOKIE':
cookie = context['cookie_name']
context['session_persistence'] = {'type': stype,
'cookie_name': cookie}
else:
context['session_persistence'] = {'type': stype}
else:
context['session_persistence'] = {}
try:
data = {'vip': {'name': context['name'],
'description': context['description'],
'pool_id': context['pool_id'],
'session_persistence':
context['session_persistence'],
'connection_limit': context['connection_limit'],
'admin_state_up': context['admin_state_up'],
}}
vip = api.lbaas.vip_update(request, context['vip_id'], **data)
msg = _('VIP %s was successfully updated.') % context['name']
LOG.debug(msg)
messages.success(request, msg)
return vip
except Exception:
msg = _('Failed to update VIP %s') % context['name']
LOG.info(msg)
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)
class UpdateMember(forms.SelfHandlingForm):
member_id = forms.CharField(label=_("ID"),
widget=forms.TextInput(
attrs={'readonly': 'readonly'}))
pool_id = forms.ThemableChoiceField(label=_("Pool"))
weight = forms.IntegerField(max_value=256, min_value=0, label=_("Weight"),
help_text=_("Relative part of requests this "
"pool member serves compared to others"))
admin_state_up = forms.ThemableChoiceField(
choices=[(True, _('UP')),
(False, _('DOWN'))],
label=_("Admin State"))
failure_url = 'horizon:project:loadbalancers:index'
def __init__(self, request, *args, **kwargs):
super(UpdateMember, self).__init__(request, *args, **kwargs)
pool_id_choices = []
try:
tenant_id = request.user.tenant_id
pools = api.lbaas.pool_list(request, tenant_id=tenant_id)
except Exception:
pools = []
exceptions.handle(request,
_('Unable to retrieve pools list.'))
pools = sorted(pools,
key=lambda pool: pool.name)
for p in pools:
pool_id_choices.append((p.id, p.name))
self.fields['pool_id'].choices = pool_id_choices
def handle(self, request, context):
context['admin_state_up'] = (context['admin_state_up'] == 'True')
try:
data = {'member': {'pool_id': context['pool_id'],
'weight': context['weight'],
'admin_state_up': context['admin_state_up']}}
member = api.lbaas.member_update(request,
context['member_id'], **data)
msg = _('Member %s was successfully updated.')\
% context['member_id']
LOG.debug(msg)
messages.success(request, msg)
return member
except Exception:
msg = _('Failed to update member %s') % context['member_id']
LOG.info(msg)
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)
class UpdateMonitor(forms.SelfHandlingForm):
monitor_id = forms.CharField(label=_("ID"),
widget=forms.TextInput(
attrs={'readonly': 'readonly'}))
delay = forms.IntegerField(
min_value=1,
label=_("Delay"),
help_text=_("The minimum time in seconds between regular checks "
"of a member. It must be greater than or equal to "
"timeout"))
timeout = forms.IntegerField(
min_value=1,
label=_("Timeout"),
help_text=_("The maximum time in seconds for a monitor to wait "
"for a reply. It must be less than or equal to delay"))
max_retries = forms.IntegerField(
max_value=10, min_value=1,
label=_("Max Retries (1~10)"),
help_text=_("Number of permissible failures before changing "
"the status of member to inactive"))
admin_state_up = forms.ThemableChoiceField(
choices=[(True, _('UP')),
(False, _('DOWN'))],
label=_("Admin State"))
failure_url = 'horizon:project:loadbalancers:index'
def __init__(self, request, *args, **kwargs):
super(UpdateMonitor, self).__init__(request, *args, **kwargs)
def clean(self):
cleaned_data = super(UpdateMonitor, self).clean()
delay = cleaned_data.get('delay')
timeout = cleaned_data.get('timeout')
if not delay >= timeout:
msg = _('Delay must be greater than or equal to timeout')
self._errors['delay'] = self.error_class([msg])
return cleaned_data
def handle(self, request, context):
context['admin_state_up'] = (context['admin_state_up'] == 'True')
try:
data = {'health_monitor': {
'delay': context['delay'],
'timeout': context['timeout'],
'max_retries': context['max_retries'],
'admin_state_up': context['admin_state_up']}}
monitor = api.lbaas.pool_health_monitor_update(
request, context['monitor_id'], **data)
msg = _('Health monitor %s was successfully updated.')\
% context['monitor_id']
LOG.debug(msg)
messages.success(request, msg)
return monitor
except Exception:
msg = _('Failed to update health monitor %s')\
% context['monitor_id']
LOG.info(msg)
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)

View File

@ -1,50 +0,0 @@
# 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.
import logging
from django.utils.translation import ugettext_lazy as _
import horizon
from openstack_dashboard.api import neutron
LOG = logging.getLogger(__name__)
class LoadBalancer(horizon.Panel):
name = _("Load Balancers")
slug = "loadbalancers"
permissions = ('openstack.services.network',)
def allowed(self, context):
request = context['request']
if not request.user.has_perms(self.permissions):
return False
try:
if not neutron.is_service_enabled(request,
config_name='enable_lb',
ext_name='lbaas'):
return False
except Exception:
LOG.error("Call to list enabled services failed. This is likely "
"due to a problem communicating with the Neutron "
"endpoint. Load Balancers panel will not be displayed.")
return False
if not super(LoadBalancer, self).allowed(context):
return False
LOG.warning(
"DEPRECATION: LBaaS v1 dashboard in Horizon is deprecated "
"in 'Newton' release and will be removed in 'Ocata' release. "
"For more detail, check Horizon Newton release notes.")
return True

View File

@ -1,566 +0,0 @@
# 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 django.core.urlresolvers import reverse
from django import shortcuts
from django import template
from django.template import defaultfilters as filters
from django.utils import http
from django.utils.http import urlencode
from django.utils.translation import pgettext_lazy
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext_lazy
from horizon import conf
from horizon import exceptions
from horizon import messages
from horizon import tables
from openstack_dashboard import api
from openstack_dashboard.dashboards.project.access_and_security.floating_ips \
import workflows
from openstack_dashboard import policy
class AddPoolLink(tables.LinkAction):
name = "addpool"
verbose_name = _("Add Pool")
url = "horizon:project:loadbalancers:addpool"
classes = ("ajax-modal",)
icon = "plus"
policy_rules = (("network", "create_pool"),)
class AddVipLink(tables.LinkAction):
name = "addvip"
verbose_name = _("Add VIP")
classes = ("ajax-modal",)
icon = "plus"
policy_rules = (("network", "create_vip"),)
def get_link_url(self, pool):
base_url = reverse("horizon:project:loadbalancers:addvip",
kwargs={'pool_id': pool.id})
return base_url
def allowed(self, request, datum=None):
if datum and datum.vip_id:
return False
return True
class AddMemberLink(tables.LinkAction):
name = "addmember"
verbose_name = _("Add Member")
url = "horizon:project:loadbalancers:addmember"
classes = ("ajax-modal",)
icon = "plus"
policy_rules = (("network", "create_member"),)
class AddMonitorLink(tables.LinkAction):
name = "addmonitor"
verbose_name = _("Add Monitor")
url = "horizon:project:loadbalancers:addmonitor"
classes = ("ajax-modal",)
icon = "plus"
policy_rules = (("network", "create_health_monitor"),)
class DeleteVipLink(policy.PolicyTargetMixin, tables.Action):
name = "deletevip"
preempt = True
verbose_name = _("Delete VIP")
policy_rules = (("network", "delete_vip"),)
action_type = "danger"
def allowed(self, request, datum=None):
if datum and datum.vip_id:
self.help_text = _("Deleting VIP %s from this pool "
"cannot be undone.") % datum.vip_id
return True
return False
def single(self, table, request, obj_id):
try:
vip_id = api.lbaas.pool_get(request, obj_id).vip_id
except Exception as e:
exceptions.handle(request,
_('Unable to locate VIP to delete. %s')
% e)
if vip_id is not None:
try:
api.lbaas.vip_delete(request, vip_id)
messages.success(request, _('Deleted VIP %s') % vip_id)
except Exception as e:
exceptions.handle(request,
_('Unable to delete VIP. %s') % e)
class DeletePoolLink(policy.PolicyTargetMixin, tables.DeleteAction):
name = "deletepool"
policy_rules = (("network", "delete_pool"),)
@staticmethod
def action_present(count):
return ungettext_lazy(
u"Delete Pool",
u"Delete Pools",
count
)
@staticmethod
def action_past(count):
return ungettext_lazy(
u"Scheduled deletion of Pool",
u"Scheduled deletion of Pools",
count
)
def allowed(self, request, datum=None):
if datum and datum.vip_id:
return False
return True
def delete(self, request, obj_id):
try:
api.lbaas.pool_delete(request, obj_id)
except Exception as e:
exceptions.handle(request,
_('Unable to delete pool. %s') % e)
class DeleteMonitorLink(policy.PolicyTargetMixin,
tables.DeleteAction):
name = "deletemonitor"
policy_rules = (("network", "delete_health_monitor"),)
@staticmethod
def action_present(count):
return ungettext_lazy(
u"Delete Monitor",
u"Delete Monitors",
count
)
@staticmethod
def action_past(count):
return ungettext_lazy(
u"Scheduled deletion of Monitor",
u"Scheduled deletion of Monitors",
count
)
def delete(self, request, obj_id):
try:
api.lbaas.pool_health_monitor_delete(request, obj_id)
except Exception as e:
exceptions.handle(request,
_('Unable to delete monitor. %s') % e)
class DeleteMemberLink(policy.PolicyTargetMixin, tables.DeleteAction):
name = "deletemember"
policy_rules = (("network", "delete_member"),)
@staticmethod
def action_present(count):
return ungettext_lazy(
u"Delete Member",
u"Delete Members",
count
)
@staticmethod
def action_past(count):
return ungettext_lazy(
u"Scheduled deletion of Member",
u"Scheduled deletion of Members",
count
)
def delete(self, request, obj_id):
try:
api.lbaas.member_delete(request, obj_id)
except Exception as e:
exceptions.handle(request,
_('Unable to delete member. %s') % e)
class UpdatePoolLink(policy.PolicyTargetMixin, tables.LinkAction):
name = "updatepool"
verbose_name = _("Edit Pool")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("network", "update_pool"),)
def get_link_url(self, pool):
base_url = reverse("horizon:project:loadbalancers:updatepool",
kwargs={'pool_id': pool.id})
return base_url
class UpdateVipLink(policy.PolicyTargetMixin, tables.LinkAction):
name = "updatevip"
verbose_name = _("Edit VIP")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("network", "update_vip"),)
def get_link_url(self, pool):
base_url = reverse("horizon:project:loadbalancers:updatevip",
kwargs={'vip_id': pool.vip_id})
return base_url
def allowed(self, request, datum=None):
if datum and not datum.vip_id:
return False
return True
class UpdateMemberLink(policy.PolicyTargetMixin, tables.LinkAction):
name = "updatemember"
verbose_name = _("Edit Member")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("network", "update_member"),)
def get_link_url(self, member):
base_url = reverse("horizon:project:loadbalancers:updatemember",
kwargs={'member_id': member.id})
return base_url
class UpdateMonitorLink(policy.PolicyTargetMixin, tables.LinkAction):
name = "updatemonitor"
verbose_name = _("Edit Monitor")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("network", "update_health_monitor"),)
def get_link_url(self, monitor):
base_url = reverse("horizon:project:loadbalancers:updatemonitor",
kwargs={'monitor_id': monitor.id})
return base_url
class AddPMAssociationLink(policy.PolicyTargetMixin,
tables.LinkAction):
name = "addassociation"
verbose_name = _("Associate Monitor")
url = "horizon:project:loadbalancers:addassociation"
classes = ("ajax-modal",)
icon = "plus"
policy_rules = (("network", "create_pool_health_monitor"),)
def allowed(self, request, datum=None):
try:
tenant_id = request.user.tenant_id
monitors = api.lbaas.pool_health_monitor_list(request,
tenant_id=tenant_id)
for m in monitors:
if m.id not in datum['health_monitors']:
return True
except Exception:
exceptions.handle(request,
_('Failed to retrieve health monitors.'))
return False
class DeletePMAssociationLink(policy.PolicyTargetMixin,
tables.LinkAction):
name = "deleteassociation"
verbose_name = _("Disassociate Monitor")
url = "horizon:project:loadbalancers:deleteassociation"
classes = ("ajax-modal",)
icon = "trash"
policy_rules = (("network", "delete_pool_health_monitor"),)
action_type = "danger"
def allowed(self, request, datum=None):
if datum and not datum['health_monitors']:
return False
return True
class AddVIPFloatingIP(policy.PolicyTargetMixin, tables.LinkAction):
"""Add floating ip to VIP
This class is extremely similar to AssociateIP from
the instances page
"""
name = "associate"
verbose_name = _("Associate Floating IP")
url = "horizon:project:access_and_security:floating_ips:associate"
classes = ("ajax-modal",)
icon = "link"
policy_rules = (("compute", "network:associate_floating_ip"),)
def allowed(self, request, pool):
if not api.network.floating_ip_supported(request):
return False
if api.network.floating_ip_simple_associate_supported(request):
return False
if hasattr(pool, "vip") and pool.vip:
vip = pool.vip
return not (hasattr(vip, "fip") and vip.fip)
return False
def get_link_url(self, datum):
base_url = reverse(self.url)
next_url = self.table.get_full_url()
params = {
workflows.IPAssociationWorkflow.redirect_param_name: next_url}
if hasattr(datum, "vip") and datum.vip:
vip = datum.vip
params['port_id'] = vip.port_id
params = urlencode(params)
return "?".join([base_url, params])
class RemoveVIPFloatingIP(policy.PolicyTargetMixin, tables.Action):
"""Remove floating IP from VIP
This class is extremely similar to the project instance table
SimpleDisassociateIP feature, but just different enough to not
be able to share much code
"""
name = "disassociate"
preempt = True
icon = "unlink"
verbose_name = _("Disassociate Floating IP")
classes = ("btn-disassociate",)
policy_rules = (("compute", "network:disassociate_floating_ip"),)
action_type = "danger"
def allowed(self, request, pool):
if not api.network.floating_ip_supported(request):
return False
if not conf.HORIZON_CONFIG["simple_ip_management"]:
return False
if hasattr(pool, "vip") and pool.vip:
vip = pool.vip
self.help_text = _('Floating IP will be removed '
'from VIP "%s".') % vip.name
return hasattr(vip, "fip") and vip.fip
return False
def single(self, table, request, pool_id):
try:
pool = api.lbaas.pool_get(request, pool_id)
fips = api.network.tenant_floating_ip_list(request)
vip_fips = [fip for fip in fips
if fip.port_id == pool.vip.port_id]
if not vip_fips:
messages.info(request, _("No floating IPs to disassociate."))
else:
api.network.floating_ip_disassociate(request,
vip_fips[0].id)
messages.success(request,
_("Successfully disassociated "
"floating IP: %s") % vip_fips[0].ip)
except Exception:
exceptions.handle(request,
_("Unable to disassociate floating IP."))
return shortcuts.redirect(request.get_full_path())
class UpdatePoolsRow(tables.Row):
ajax = True
def get_data(self, request, pool_id):
pool = api.lbaas.pool_get(request, pool_id)
try:
vip = api.lbaas.vip_get(request, pool.vip_id)
pool.vip = vip
except Exception:
pass
try:
subnet = api.neutron.subnet_get(request, pool.subnet_id)
pool.subnet_name = subnet.cidr
except Exception:
pool.subnet_name = pool.subnet_id
return pool
STATUS_CHOICES = (
("Active", True),
("Down", True),
("Error", False),
)
STATUS_DISPLAY_CHOICES = (
("Active", pgettext_lazy("Current status of a Pool",
u"Active")),
("Down", pgettext_lazy("Current status of a Pool",
u"Down")),
("Error", pgettext_lazy("Current status of a Pool",
u"Error")),
("Created", pgettext_lazy("Current status of a Pool",
u"Created")),
("Pending_Create", pgettext_lazy("Current status of a Pool",
u"Pending Create")),
("Pending_Update", pgettext_lazy("Current status of a Pool",
u"Pending Update")),
("Pending_Delete", pgettext_lazy("Current status of a Pool",
u"Pending Delete")),
("Inactive", pgettext_lazy("Current status of a Pool",
u"Inactive")),
)
ADMIN_STATE_DISPLAY_CHOICES = (
("UP", pgettext_lazy("Admin state of a Load balancer", u"UP")),
("DOWN", pgettext_lazy("Admin state of a Load balancer", u"DOWN")),
)
def get_vip_name(pool):
if hasattr(pool, "vip") and pool.vip:
template_name = 'project/loadbalancers/_pool_table_vip_cell.html'
context = {"vip": pool.vip, }
return template.loader.render_to_string(template_name, context)
else:
return None
def get_subnet(pool):
if hasattr(pool, "subnet") and pool.subnet:
template_name = 'project/loadbalancers/_pool_table_subnet_cell.html'
context = {"subnet": pool.subnet}
return template.loader.render_to_string(template_name, context)
else:
return None
class PoolsTable(tables.DataTable):
METHOD_DISPLAY_CHOICES = (
("round_robin", pgettext_lazy("load balancing method",
u"Round Robin")),
("least_connections", pgettext_lazy("load balancing method",
u"Least Connections")),
("source_ip", pgettext_lazy("load balancing method",
u"Source IP")),
)
name = tables.Column("name_or_id",
verbose_name=_("Name"),
link="horizon:project:loadbalancers:pooldetails")
description = tables.Column('description', verbose_name=_("Description"))
provider = tables.Column('provider', verbose_name=_("Provider"),
filters=(lambda v: filters.default(v, _('N/A')),))
subnet_name = tables.Column(get_subnet, verbose_name=_("Subnet"))
protocol = tables.Column('protocol', verbose_name=_("Protocol"))
method = tables.Column('lb_method',
verbose_name=_("LB Method"),
display_choices=METHOD_DISPLAY_CHOICES)
status = tables.Column('status',
verbose_name=_("Status"),
status=True,
status_choices=STATUS_CHOICES,
display_choices=STATUS_DISPLAY_CHOICES)
vip_name = tables.Column(get_vip_name, verbose_name=_("VIP"))
admin_state = tables.Column("admin_state",
verbose_name=_("Admin State"),
display_choices=ADMIN_STATE_DISPLAY_CHOICES)
class Meta(object):
name = "poolstable"
verbose_name = _("Pools")
status_columns = ["status"]
row_class = UpdatePoolsRow
table_actions = (AddPoolLink, DeletePoolLink)
row_actions = (UpdatePoolLink, AddVipLink, UpdateVipLink,
DeleteVipLink, AddPMAssociationLink,
DeletePMAssociationLink, DeletePoolLink,
AddVIPFloatingIP, RemoveVIPFloatingIP)
def get_pool_link(member):
return reverse("horizon:project:loadbalancers:pooldetails",
args=(http.urlquote(member.pool_id),))
def get_member_link(member):
return reverse("horizon:project:loadbalancers:memberdetails",
args=(http.urlquote(member.id),))
class UpdateMemberRow(tables.Row):
ajax = True
def get_data(self, request, member_id):
member = api.lbaas.member_get(request, member_id)
try:
pool = api.lbaas.pool_get(request, member.pool_id)
member.pool_name = pool.name
except Exception:
member.pool_name = member.pool_id
return member
class MembersTable(tables.DataTable):
address = tables.Column('address',
verbose_name=_("IP Address"),
link=get_member_link,
attrs={'data-type': "ip"})
protocol_port = tables.Column('protocol_port',
verbose_name=_("Protocol Port"))
weight = tables.Column('weight',
verbose_name=_("Weight"))
pool_name = tables.Column('pool_name',
verbose_name=_("Pool"), link=get_pool_link)
status = tables.Column('status',
verbose_name=_("Status"),
status=True,
status_choices=STATUS_CHOICES,
display_choices=STATUS_DISPLAY_CHOICES)
admin_state = tables.Column("admin_state",
verbose_name=_("Admin State"),
display_choices=ADMIN_STATE_DISPLAY_CHOICES)
class Meta(object):
name = "memberstable"
verbose_name = _("Members")
status_columns = ["status"]
row_class = UpdateMemberRow
table_actions = (AddMemberLink, DeleteMemberLink)
row_actions = (UpdateMemberLink, DeleteMemberLink)
def get_monitor_details(monitor):
if monitor.type in ('HTTP', 'HTTPS'):
return ("%(http_method)s %(url_path)s => %(codes)s" %
{'http_method': monitor.http_method,
'url_path': monitor.url_path,
'codes': monitor.expected_codes})
else:
return _("-")
class MonitorsTable(tables.DataTable):
monitor_type = tables.Column(
"type", verbose_name=_("Monitor Type"),
link="horizon:project:loadbalancers:monitordetails")
delay = tables.Column("delay", verbose_name=_("Delay"))
timeout = tables.Column("timeout", verbose_name=_("Timeout"))
max_retries = tables.Column("max_retries", verbose_name=_("Max Retries"))
details = tables.Column(get_monitor_details, verbose_name=_("Details"))
admin_state = tables.Column("admin_state",
verbose_name=_("Admin State"),
display_choices=ADMIN_STATE_DISPLAY_CHOICES)
class Meta(object):
name = "monitorstable"
verbose_name = _("Monitors")
table_actions = (AddMonitorLink, DeleteMonitorLink)
row_actions = (UpdateMonitorLink, DeleteMonitorLink)

View File

@ -1,151 +0,0 @@
# 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 django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import tabs
from openstack_dashboard import api
from openstack_dashboard.dashboards.project.loadbalancers import tables
class PoolsTab(tabs.TableTab):
table_classes = (tables.PoolsTable,)
name = _("Pools")
slug = "pools"
template_name = "horizon/common/_detail_table.html"
def get_poolstable_data(self):
pools = []
try:
request = self.tab_group.request
tenant_id = self.request.user.tenant_id
pools = api.lbaas.pool_list(request,
tenant_id=tenant_id)
fips = None
for pool in pools:
if hasattr(pool, "vip") and pool.vip:
if not fips:
fips = api.network.tenant_floating_ip_list(request)
vip_fip = [fip for fip in fips
if fip.port_id == pool.vip.port_id]
if vip_fip:
pool.vip.fip = vip_fip[0]
except Exception:
exceptions.handle(self.tab_group.request,
_('Unable to retrieve pools list.'))
return pools
class MembersTab(tabs.TableTab):
table_classes = (tables.MembersTable,)
name = _("Members")
slug = "members"
template_name = "horizon/common/_detail_table.html"
def get_memberstable_data(self):
try:
tenant_id = self.request.user.tenant_id
members = api.lbaas.member_list(self.tab_group.request,
tenant_id=tenant_id)
except Exception:
members = []
exceptions.handle(self.tab_group.request,
_('Unable to retrieve member list.'))
return members
class MonitorsTab(tabs.TableTab):
table_classes = (tables.MonitorsTable,)
name = _("Monitors")
slug = "monitors"
template_name = "horizon/common/_detail_table.html"
def get_monitorstable_data(self):
try:
tenant_id = self.request.user.tenant_id
monitors = api.lbaas.pool_health_monitor_list(
self.tab_group.request, tenant_id=tenant_id)
except Exception:
monitors = []
exceptions.handle(self.tab_group.request,
_('Unable to retrieve monitor list.'))
return monitors
class LoadBalancerTabs(tabs.TabGroup):
slug = "lbtabs"
tabs = (PoolsTab, MembersTab, MonitorsTab)
sticky = True
class PoolDetailsTab(tabs.Tab):
name = _("Pool Details")
slug = "pooldetails"
template_name = "project/loadbalancers/_pool_details.html"
def get_context_data(self, request):
pool = self.tab_group.kwargs['pool']
return {'pool': pool}
class VipDetailsTab(tabs.Tab):
name = _("VIP Details")
slug = "vipdetails"
template_name = "project/loadbalancers/_vip_details.html"
def get_context_data(self, request):
vip = self.tab_group.kwargs['vip']
return {'vip': vip}
class MemberDetailsTab(tabs.Tab):
name = _("Member Details")
slug = "memberdetails"
template_name = "project/loadbalancers/_member_details.html"
def get_context_data(self, request):
member = self.tab_group.kwargs['member']
return {'member': member}
class MonitorDetailsTab(tabs.Tab):
name = _("Monitor Details")
slug = "monitordetails"
template_name = "project/loadbalancers/_monitor_details.html"
def get_context_data(self, request):
monitor = self.tab_group.kwargs['monitor']
return {'monitor': monitor}
class PoolDetailsTabs(tabs.TabGroup):
slug = "pooltabs"
tabs = (PoolDetailsTab,)
class VipDetailsTabs(tabs.TabGroup):
slug = "viptabs"
tabs = (VipDetailsTab,)
class MemberDetailsTabs(tabs.TabGroup):
slug = "membertabs"
tabs = (MemberDetailsTab,)
class MonitorDetailsTabs(tabs.TabGroup):
slug = "monitortabs"
tabs = (MonitorDetailsTab,)

View File

@ -1,27 +0,0 @@
{% load i18n %}
<p>
{% blocktrans trimmed %}
Assign a name and description for the pool. Choose one subnet where all
members of this pool must be on. Select the protocol and load balancing
method for this pool. Admin State is UP (checked) by default.
{% endblocktrans %}
</p>
<p><label>{% blocktrans trimmed %}Load Balancing Method{% endblocktrans %}</label><br/>
{% blocktrans trimmed %}
Use one of these load balancing methods to distribute incoming requests:
{% endblocktrans %}
<div>
<dl>
<dt>{% blocktrans trimmed %}Round robin{% endblocktrans %}</dt>
<dd>{% blocktrans trimmed %}Rotates requests evenly between multiple
instances.{% endblocktrans %}</dd>
<dt>{% blocktrans trimmed %}Source IP{% endblocktrans %}</dt>
<dd>{% blocktrans trimmed %}Requests from a unique source IP address are consistently
directed to the same instance.{% endblocktrans %}</dd>
<dt>{% blocktrans trimmed %}Least connections{% endblocktrans %}</dt>
<dd>{% blocktrans trimmed %}Allocates requests to the instance with the least number of
active connections.{% endblocktrans %}</dd>
</dl>
</div>
</p>

View File

@ -1,16 +0,0 @@
{% load i18n %}
<p>
{% blocktrans trimmed %}
Create a VIP for this pool. Assign a name, description, IP address, port,
and maximum connections allowed for the VIP. Choose the protocol and session persistence
method for the VIP. Admin State is UP (checked) by default.
{% endblocktrans %}
</p>
<p><label>{% blocktrans trimmed %}IP address{% endblocktrans %}</label><br/>
{% blocktrans trimmed %}
When no IP address is provided, the VIP will obtain an address from
the selected subnet. If a specific IP address is desired, it may be provided and
must also be an address within the selected subnet.
{% endblocktrans %}
</p>

View File

@ -1,30 +0,0 @@
{% load i18n sizeformat parse_date %}
<div class="detail">
<dl class="dl-horizontal">
<dt>{% trans "ID" %}</dt>
<dd>{{ member.id }}</dd>
<dt>{% trans "Project ID" %}</dt>
<dd>{{ member.tenant_id }}</dd>
<dt>{% trans "Pool" %}</dt>
{% url 'horizon:project:loadbalancers:pooldetails' member.pool_id as pool_url %}
<dd><a href="{{ pool_url }}">{{ member.pool.name_or_id }}</a></dd>
<dt>{% trans "Address" %}</dt>
<dd>{{ member.address }}</dd>
<dt>{% trans "Protocol Port" %}</dt>
<dd>{{ member.protocol_port }}</dd>
<dt>{% trans "Weight" %}</dt>
<dd>{{ member.weight }}</dd>
<dt>{% trans "Admin State Up" %}</dt>
<dd>{{ member.admin_state_up|yesno|capfirst }}</dd>
<dt>{% trans "Status" %}</dt>
<dd>{{ member.status }}</dd>
</dl>
</div>

View File

@ -1,5 +0,0 @@
{% block main %}
{{ table.render }}
{% endblock %}

View File

@ -1,51 +0,0 @@
{% load i18n sizeformat parse_date %}
<div class="detail">
<dl class="dl-horizontal">
<dt>{% trans "ID" %}</dt>
<dd>{{ monitor.id }}</dd>
<dt>{% trans "Project ID" %}</dt>
<dd>{{ monitor.tenant_id }}</dd>
<dt>{% trans "Type" %}</dt>
<dd>{{ monitor.type }}</dd>
<dt>{% trans "Delay" %}</dt>
<dd>{{ monitor.delay }}</dd>
<dt>{% trans "Timeout" %}</dt>
<dd>{{ monitor.timeout }}</dd>
<dt>{% trans "Max Retries" %}</dt>
<dd>{{ monitor.max_retries }}</dd>
{% if monitor.type == 'HTTP' or monitor.type == 'HTTPS' %}
<dt>{% trans "HTTP Method" %}</dt>
<dd>{{ monitor.http_method }}</dd>
<dt>{% trans "URL Path" %}</dt>
<dd>{{ monitor.url_path }}</dd>
<dt>{% trans "Expected Codes" %}</dt>
<dd>{{ monitor.expected_codes }}</dd>
{% endif %}
<dt>{% trans "Admin State Up" %}</dt>
<dd>{{ monitor.admin_state_up|yesno|capfirst }}</dd>
</dl>
<dl class="dl-horizontal">
<h4>{% trans "Pools" %}</h4>
<hr class="header_rule">
{% if monitor.pools %}
<ul>
{% for pool in monitor.pools %}
{% url 'horizon:project:loadbalancers:pooldetails' pool.id as pool_url %}
<li><a href="{{ pool_url }}">{{ pool.name_or_id }}</a></li>
{% endfor %}
{% else %}
{% trans "None" %}
{% endif %}
</dl>
</div>

View File

@ -1,5 +0,0 @@
{% block main %}
{{ table.render }}
{% endblock %}

View File

@ -1,74 +0,0 @@
{% load i18n sizeformat parse_date %}
<div class="detail">
<dl class="dl-horizontal">
<dt>{% trans "ID" %}</dt>
<dd>{{ pool.id }}</dd>
<dt>{% trans "Name" %}</dt>
<dd>{{ pool.name|default:_("-") }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ pool.description|default:_("-") }}</dd>
<dt>{% trans "Project ID" %}</dt>
<dd>{{ pool.tenant_id }}</dd>
<dt>{% trans "VIP" %}</dt>
{% if pool.vip_id %}
{% url 'horizon:project:loadbalancers:vipdetails' pool.vip_id as vip_url %}
<dd><a href="{{ vip_url }}">{{ pool.vip.name_or_id }}</a></dd>
{% else %}
<dd>{% trans "None" %}</dd>
{% endif %}
<dt>{% trans "Provider" %}</dt>
<dd>{{ pool.provider|default:_("N/A") }}</dd>
<dt>{% trans "Subnet" %}</dt>
{% url 'horizon:project:networks:subnets:detail' pool.subnet_id as subnet_url %}
<dd><a href="{{ subnet_url }}">{{ pool.subnet.name_or_id }} {{ pool.subnet.cidr }}</a></dd>
<dt>{% trans "Protocol" %}</dt>
<dd>{{ pool.protocol }}</dd>
<dt>{% trans "Load Balancing Method" %}</dt>
<dd>{{ pool.lb_method }}</dd>
<dt>{% trans "Admin State Up" %}</dt>
<dd>{{ pool.admin_state_up|yesno|capfirst }}</dd>
<dt>{% trans "Status" %}</dt>
<dd>{{ pool.status }}</dd>
</dl>
<dl class="dl-horizontal">
<h4>{% trans "Members" %}</h4>
<hr class="header_rule">
{% if pool.members %}
<ul>
{% for member in pool.members %}
{% url 'horizon:project:loadbalancers:memberdetails' member.id as member_url %}
<li><a href="{{ member_url }}">{{ member.address }}:{{ member.protocol_port }}</a></li>
{% endfor %}
<ul>
{% else %}
{% trans "None" %}
{% endif %}
</dl>
<dl class="dl-horizontal">
<h4>{% trans "Health Monitors" %}</h4>
<hr class="header_rule">
{% if pool.health_monitors %}
<ul>
{% for monitor in pool.health_monitors %}
{% url 'horizon:project:loadbalancers:monitordetails' monitor.id as monitor_url %}
<li><a href="{{ monitor_url }}">{{ monitor.display_name }}</a></li>
{% endfor %}
</ul>
{% else %}
{% trans "None" %}
{% endif %}
</dl>
</div>

View File

@ -1,8 +0,0 @@
<ul>
<li>
{% if subnet.name|length > 0 %}
<b>{{ subnet.name }}</b>
{% endif %}
{{ subnet.cidr }}
</li>
</ul>

View File

@ -1,9 +0,0 @@
{% load i18n %}
{% url 'horizon:project:loadbalancers:vipdetails' vip.id as vip_url %}
<a href="{{ vip_url }}">{{ vip.name }}</a>
<br/>
{% trans "Address:" %} {{ vip.address }}
{% if vip.fip %}
<br/>
{% trans "Floating IP:" %} {{ vip.fip.floating_ip_address }}
{% endif %}

View File

@ -1,5 +0,0 @@
{% block main %}
{{ poolstable.render }}
{% endblock %}

View File

@ -1,7 +0,0 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "You may update member attributes here: edit pool, weight or admin state." %}</p>
{% endblock %}

View File

@ -1,7 +0,0 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "You may update health monitor attributes here: edit delay, timeout, max retries or admin state." %}</p>
{% endblock %}

View File

@ -1,7 +0,0 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "You may update pool attributes here: edit name, description, load balancing method or admin state." %}</p>
{% endblock %}

View File

@ -1,7 +0,0 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "You may update VIP attributes here: edit name, description, pool, session persistence, connection limit or admin state." %}</p>
{% endblock %}

View File

@ -1,67 +0,0 @@
{% load i18n sizeformat parse_date %}
<div class="detail">
<dl class="dl-horizontal">
<dt>{% trans "ID" %}</dt>
<dd>{{ vip.id }}</dd>
<dt>{% trans "Name" %}</dt>
<dd>{{ vip.name|default:_("-") }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ vip.description|default:_("-") }}</dd>
<dt>{% trans "Project ID" %}</dt>
<dd>{{ vip.tenant_id }}</dd>
<dt>{% trans "Subnet" %}</dt>
{% url 'horizon:project:networks:subnets:detail' vip.subnet_id as subnet_url %}
<dd><a href="{{ subnet_url }}">{{ vip.subnet.name_or_id }} {{ vip.subnet.cidr }}</a></dd>
<dt>{% trans "Address" %}</dt>
<dd>{{ vip.address }}</dd>
{% if vip.fip %}
<dt>{% trans "Floating IP" %}</dt>
<dd>{{ vip.fip.floating_ip_address }}</dd>
{% endif %}
<dt>{% trans "Protocol Port" %}</dt>
<dd>{{ vip.protocol_port }}</dd>
<dt>{% trans "Protocol" %}</dt>
<dd>{{ vip.protocol }}</dd>
<dt>{% trans "Pool" %}</dt>
{% url 'horizon:project:loadbalancers:pooldetails' vip.pool_id as pool_url %}
<dd><a href="{{ pool_url }}">{{ vip.pool.name_or_id }}</a></dd>
<dt>{% trans "Port ID" %}</dt>
{% url 'horizon:project:networks:ports:detail' vip.port_id as port_url %}
<dd><a href="{{ port_url }}">{{ vip.port_id }}</a></dd>
<dt>{% trans "Session Persistence" %}</dt>
{% if vip.session_persistence %}
<dd>
{% blocktrans with persistence_type=vip.session_persistence.type %}Type: {{ persistence_type }}{% endblocktrans %}
</dd>
{% if vip.session_persistence.cookie_name %}
<dd>
{% blocktrans with cookie_name=vip.session_persistence.cookie_name %}Cookie Name: {{ cookie_name }}{% endblocktrans %}
</dd>
{% endif %}
{% else %}
<dd>{% trans "None" %}</dd>
{% endif %}
<dt>{% trans "Connection Limit" %}</dt>
<dd>{{ vip.connection_limit }}</dd>
<dt>{% trans "Admin State Up" %}</dt>
<dd>{{ vip.admin_state_up|yesno|capfirst }}</dd>
<dt>{% trans "Status" %}</dt>
<dd>{{ vip.status }}</dd>
</dl>
</div>

View File

@ -1,11 +0,0 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Load Balancer" %}{% endblock %}
{% block main %}
<div class="row">
<div class="col-sm-12">
{{ tab_group.render }}
</div>
</div>
{% endblock %}

View File

@ -1,7 +0,0 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Edit Member" %}{% endblock %}
{% block main %}
{% include 'project/loadbalancers/_updatemember.html' %}
{% endblock %}

View File

@ -1,7 +0,0 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Edit Monitor" %}{% endblock %}
{% block main %}
{% include 'project/loadbalancers/_updatemonitor.html' %}
{% endblock %}

View File

@ -1,7 +0,0 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Edit Pool" %}{% endblock %}
{% block main %}
{% include 'project/loadbalancers/_updatepool.html' %}
{% endblock %}

View File

@ -1,7 +0,0 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Edit VIP" %}{% endblock %}
{% block main %}
{% include 'project/loadbalancers/_updatevip.html' %}
{% endblock %}

File diff suppressed because it is too large Load Diff

View File

@ -1,50 +0,0 @@
# 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 django.conf.urls import url
from openstack_dashboard.dashboards.project.loadbalancers import views
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^\?tab=lbtabs__members$', views.IndexView.as_view(), name='members'),
url(r'^\?tab=lbtabs__monitors$',
views.IndexView.as_view(), name='monitors'),
url(r'^addpool$', views.AddPoolView.as_view(), name='addpool'),
url(r'^updatepool/(?P<pool_id>[^/]+)/$',
views.UpdatePoolView.as_view(), name='updatepool'),
url(r'^addvip/(?P<pool_id>[^/]+)/$',
views.AddVipView.as_view(), name='addvip'),
url(r'^updatevip/(?P<vip_id>[^/]+)/$',
views.UpdateVipView.as_view(), name='updatevip'),
url(r'^addmember$', views.AddMemberView.as_view(), name='addmember'),
url(r'^updatemember/(?P<member_id>[^/]+)/$',
views.UpdateMemberView.as_view(), name='updatemember'),
url(r'^addmonitor$', views.AddMonitorView.as_view(), name='addmonitor'),
url(r'^updatemonitor/(?P<monitor_id>[^/]+)/$',
views.UpdateMonitorView.as_view(), name='updatemonitor'),
url(r'^association/add/(?P<pool_id>[^/]+)/$',
views.AddPMAssociationView.as_view(), name='addassociation'),
url(r'^association/delete/(?P<pool_id>[^/]+)/$',
views.DeletePMAssociationView.as_view(), name='deleteassociation'),
url(r'^pool/(?P<pool_id>[^/]+)/$',
views.PoolDetailsView.as_view(), name='pooldetails'),
url(r'^vip/(?P<vip_id>[^/]+)/$',
views.VipDetailsView.as_view(), name='vipdetails'),
url(r'^member/(?P<member_id>[^/]+)/$',
views.MemberDetailsView.as_view(), name='memberdetails'),
url(r'^monitor/(?P<monitor_id>[^/]+)/$',
views.MonitorDetailsView.as_view(), name='monitordetails'),
]

View File

@ -1,31 +0,0 @@
# Copyright 2014, NEC Corporation
#
# 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 django.utils.translation import ugettext_lazy as _
def get_monitor_display_name(monitor):
fields = ['type', 'delay', 'max_retries', 'timeout']
if monitor.type in ['HTTP', 'HTTPS']:
fields.extend(['url_path', 'expected_codes', 'http_method'])
name = _("%(type)s: url:%(url_path)s "
"method:%(http_method)s codes:%(expected_codes)s "
"delay:%(delay)d retries:%(max_retries)d "
"timeout:%(timeout)d")
else:
name = _("%(type)s delay:%(delay)d "
"retries:%(max_retries)d "
"timeout:%(timeout)d")
params = dict((key, getattr(monitor, key)) for key in fields)
return name % params

View File

@ -1,422 +0,0 @@
# 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 django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
from horizon import tabs
from horizon.utils import memoized
from horizon import workflows
from openstack_dashboard import api
from openstack_dashboard.dashboards.project.loadbalancers \
import forms as project_forms
from openstack_dashboard.dashboards.project.loadbalancers \
import tables as project_tables
from openstack_dashboard.dashboards.project.loadbalancers \
import tabs as project_tabs
from openstack_dashboard.dashboards.project.loadbalancers import utils
from openstack_dashboard.dashboards.project.loadbalancers \
import workflows as project_workflows
class IndexView(tabs.TabbedTableView):
tab_group_class = (project_tabs.LoadBalancerTabs)
template_name = 'project/loadbalancers/details_tabs.html'
page_title = _("Load Balancer")
class AddPoolView(workflows.WorkflowView):
workflow_class = project_workflows.AddPool
class AddVipView(workflows.WorkflowView):
workflow_class = project_workflows.AddVip
def get_initial(self):
initial = super(AddVipView, self).get_initial()
initial['pool_id'] = self.kwargs['pool_id']
try:
pool = api.lbaas.pool_get(self.request, initial['pool_id'])
initial['subnet'] = api.neutron.subnet_get(
self.request, pool.subnet_id).cidr
except Exception as e:
initial['subnet'] = ''
msg = _('Unable to retrieve pool subnet. %s') % e
exceptions.handle(self.request, msg)
return initial
class AddMemberView(workflows.WorkflowView):
workflow_class = project_workflows.AddMember
class AddMonitorView(workflows.WorkflowView):
workflow_class = project_workflows.AddMonitor
class PoolDetailsView(tabs.TabView):
tab_group_class = project_tabs.PoolDetailsTabs
template_name = 'horizon/common/_detail.html'
page_title = "{{ pool.name|default:pool.id }}"
@memoized.memoized_method
def get_data(self):
pid = self.kwargs['pool_id']
try:
pool = api.lbaas.pool_get(self.request, pid)
except Exception:
pool = []
exceptions.handle(self.request,
_('Unable to retrieve pool details.'))
else:
for monitor in pool.health_monitors:
display_name = utils.get_monitor_display_name(monitor)
setattr(monitor, 'display_name', display_name)
return pool
def get_context_data(self, **kwargs):
context = super(PoolDetailsView, self).get_context_data(**kwargs)
pool = self.get_data()
context['pool'] = pool
table = project_tables.PoolsTable(self.request)
context["url"] = self.get_redirect_url()
context["actions"] = table.render_row_actions(pool)
return context
def get_tabs(self, request, *args, **kwargs):
pool = self.get_data()
return self.tab_group_class(self.request, pool=pool, **kwargs)
@staticmethod
def get_redirect_url():
return reverse_lazy("horizon:project:loadbalancers:index")
class VipDetailsView(tabs.TabView):
tab_group_class = project_tabs.VipDetailsTabs
template_name = 'horizon/common/_detail.html'
page_title = "{{ vip.name|default:vip_id }}"
@memoized.memoized_method
def get_data(self):
vid = self.kwargs['vip_id']
vip = []
try:
vip = api.lbaas.vip_get(self.request, vid)
fips = api.network.tenant_floating_ip_list(self.request)
vip_fip = [fip for fip in fips
if fip.port_id == vip.port.id]
if vip_fip:
vip.fip = vip_fip[0]
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve VIP details.'))
return vip
def get_context_data(self, **kwargs):
context = super(VipDetailsView, self).get_context_data(**kwargs)
vip = self.get_data()
context['vip'] = vip
vip_nav = vip.pool.name_or_id
breadcrumb = [
(vip_nav,
reverse('horizon:project:loadbalancers:vipdetails',
args=(vip.id,))),
(_("VIP"), None)
]
context["custom_breadcrumb"] = breadcrumb
return context
def get_tabs(self, request, *args, **kwargs):
vip = self.get_data()
return self.tab_group_class(request, vip=vip, **kwargs)
@staticmethod
def get_redirect_url():
return reverse("horizon:project:loadbalancers:index")
class MemberDetailsView(tabs.TabView):
tab_group_class = project_tabs.MemberDetailsTabs
template_name = 'horizon/common/_detail.html'
page_title = "{{ member.name|default:member.id }}"
@memoized.memoized_method
def get_data(self):
mid = self.kwargs['member_id']
try:
return api.lbaas.member_get(self.request, mid)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve member details.'))
def get_context_data(self, **kwargs):
context = super(MemberDetailsView, self).get_context_data(**kwargs)
member = self.get_data()
context['member'] = member
member_nav = member.pool.name_or_id
breadcrumb = [
(member_nav,
reverse('horizon:project:loadbalancers:pooldetails',
args=(member.pool.id,))),
(_("Members"), reverse('horizon:project:loadbalancers:members')),
]
context["custom_breadcrumb"] = breadcrumb
table = project_tables.MembersTable(self.request)
context["url"] = self.get_redirect_url()
context["actions"] = table.render_row_actions(member)
return context
def get_tabs(self, request, *args, **kwargs):
member = self.get_data()
return self.tab_group_class(request, member=member, **kwargs)
@staticmethod
def get_redirect_url():
return reverse_lazy("horizon:project:loadbalancers:index")
class MonitorDetailsView(tabs.TabView):
tab_group_class = project_tabs.MonitorDetailsTabs
template_name = 'horizon/common/_detail.html'
page_title = "{{ monitor.name|default:monitor.id }}"
@memoized.memoized_method
def get_data(self):
mid = self.kwargs['monitor_id']
try:
return api.lbaas.pool_health_monitor_get(self.request, mid)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve monitor details.'))
def get_context_data(self, **kwargs):
context = super(MonitorDetailsView, self).get_context_data(**kwargs)
monitor = self.get_data()
context['monitor'] = monitor
breadcrumb = [
(_("Monitors"), reverse('horizon:project:loadbalancers:monitors')),
]
context["custom_breadcrumb"] = breadcrumb
table = project_tables.MonitorsTable(self.request)
context["url"] = self.get_redirect_url()
context["actions"] = table.render_row_actions(monitor)
return context
def get_tabs(self, request, *args, **kwargs):
monitor = self.get_data()
return self.tab_group_class(request, monitor=monitor, **kwargs)
@staticmethod
def get_redirect_url():
return reverse_lazy("horizon:project:loadbalancers:index")
class UpdatePoolView(forms.ModalFormView):
form_class = project_forms.UpdatePool
form_id = "update_pool_form"
modal_header = _("Edit Pool")
template_name = "project/loadbalancers/updatepool.html"
context_object_name = 'pool'
submit_label = _("Save Changes")
submit_url = "horizon:project:loadbalancers:updatepool"
success_url = reverse_lazy("horizon:project:loadbalancers:index")
page_title = _("Edit Pool")
def get_context_data(self, **kwargs):
context = super(UpdatePoolView, self).get_context_data(**kwargs)
context["pool_id"] = self.kwargs['pool_id']
args = (self.kwargs['pool_id'],)
context['submit_url'] = reverse(self.submit_url, args=args)
return context
@memoized.memoized_method
def _get_object(self, *args, **kwargs):
pool_id = self.kwargs['pool_id']
try:
return api.lbaas.pool_get(self.request, pool_id)
except Exception as e:
redirect = self.success_url
msg = _('Unable to retrieve pool details. %s') % e
exceptions.handle(self.request, msg, redirect=redirect)
def get_initial(self):
pool = self._get_object()
return {'name': pool['name'],
'pool_id': pool['id'],
'description': pool['description'],
'lb_method': pool['lb_method'],
'admin_state_up': pool['admin_state_up']}
class UpdateVipView(forms.ModalFormView):
form_class = project_forms.UpdateVip
form_id = "update_vip_form"
modal_header = _("Edit VIP")
template_name = "project/loadbalancers/updatevip.html"
context_object_name = 'vip'
submit_label = _("Save Changes")
submit_url = "horizon:project:loadbalancers:updatevip"
success_url = reverse_lazy("horizon:project:loadbalancers:index")
page_title = _("Edit VIP")
def get_context_data(self, **kwargs):
context = super(UpdateVipView, self).get_context_data(**kwargs)
context["vip_id"] = self.kwargs['vip_id']
args = (self.kwargs['vip_id'],)
context['submit_url'] = reverse(self.submit_url, args=args)
return context
@memoized.memoized_method
def _get_object(self, *args, **kwargs):
vip_id = self.kwargs['vip_id']
try:
return api.lbaas.vip_get(self.request, vip_id)
except Exception as e:
redirect = self.success_url
msg = _('Unable to retrieve VIP details. %s') % e
exceptions.handle(self.request, msg, redirect=redirect)
def get_initial(self):
vip = self._get_object()
persistence = getattr(vip, 'session_persistence', None)
if persistence:
stype = persistence['type']
if stype == 'APP_COOKIE':
cookie = persistence['cookie_name']
else:
cookie = ''
else:
stype = ''
cookie = ''
return {'name': vip['name'],
'vip_id': vip['id'],
'description': vip['description'],
'pool_id': vip['pool_id'],
'session_persistence': stype,
'cookie_name': cookie,
'connection_limit': vip['connection_limit'],
'admin_state_up': vip['admin_state_up']}
class UpdateMemberView(forms.ModalFormView):
form_class = project_forms.UpdateMember
form_id = "update_pool_form"
modal_header = _("Edit Member")
template_name = "project/loadbalancers/updatemember.html"
context_object_name = 'member'
submit_label = _("Save Changes")
submit_url = "horizon:project:loadbalancers:updatemember"
success_url = reverse_lazy("horizon:project:loadbalancers:index")
page_title = _("Edit Member")
def get_context_data(self, **kwargs):
context = super(UpdateMemberView, self).get_context_data(**kwargs)
context["member_id"] = self.kwargs['member_id']
args = (self.kwargs['member_id'],)
context['submit_url'] = reverse(self.submit_url, args=args)
return context
@memoized.memoized_method
def _get_object(self, *args, **kwargs):
member_id = self.kwargs['member_id']
try:
return api.lbaas.member_get(self.request, member_id)
except Exception as e:
redirect = self.success_url
msg = _('Unable to retrieve member details. %s') % e
exceptions.handle(self.request, msg, redirect=redirect)
def get_initial(self):
member = self._get_object()
return {'member_id': member['id'],
'pool_id': member['pool_id'],
'weight': member['weight'],
'admin_state_up': member['admin_state_up']}
class UpdateMonitorView(forms.ModalFormView):
form_class = project_forms.UpdateMonitor
form_id = "update_monitor_form"
modal_header = _("Edit Monitor")
template_name = "project/loadbalancers/updatemonitor.html"
context_object_name = 'monitor'
submit_label = _("Save Changes")
submit_url = "horizon:project:loadbalancers:updatemonitor"
success_url = reverse_lazy("horizon:project:loadbalancers:index")
page_title = _("Edit Monitor")
def get_context_data(self, **kwargs):
context = super(UpdateMonitorView, self).get_context_data(**kwargs)
context["monitor_id"] = self.kwargs['monitor_id']
args = (self.kwargs['monitor_id'],)
context['submit_url'] = reverse(self.submit_url, args=args)
return context
@memoized.memoized_method
def _get_object(self, *args, **kwargs):
monitor_id = self.kwargs['monitor_id']
try:
return api.lbaas.pool_health_monitor_get(self.request, monitor_id)
except Exception as e:
redirect = self.success_url
msg = _('Unable to retrieve health monitor details. %s') % e
exceptions.handle(self.request, msg, redirect=redirect)
def get_initial(self):
monitor = self._get_object()
return {'monitor_id': monitor['id'],
'delay': monitor['delay'],
'timeout': monitor['timeout'],
'max_retries': monitor['max_retries'],
'admin_state_up': monitor['admin_state_up']}
class AddPMAssociationView(workflows.WorkflowView):
workflow_class = project_workflows.AddPMAssociation
def get_initial(self):
initial = super(AddPMAssociationView, self).get_initial()
initial['pool_id'] = self.kwargs['pool_id']
try:
pool = api.lbaas.pool_get(self.request, initial['pool_id'])
initial['pool_name'] = pool.name
initial['pool_monitors'] = pool.health_monitors
except Exception as e:
msg = _('Unable to retrieve pool. %s') % e
exceptions.handle(self.request, msg)
return initial
class DeletePMAssociationView(workflows.WorkflowView):
workflow_class = project_workflows.DeletePMAssociation
def get_initial(self):
initial = super(DeletePMAssociationView, self).get_initial()
initial['pool_id'] = self.kwargs['pool_id']
try:
pool = api.lbaas.pool_get(self.request, initial['pool_id'])
initial['pool_name'] = pool.name
initial['pool_monitors'] = pool.health_monitors
except Exception as e:
msg = _('Unable to retrieve pool. %s') % e
exceptions.handle(self.request, msg)
return initial

View File

@ -1,745 +0,0 @@
# 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.
import logging
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
from horizon.utils import validators
from horizon import workflows
from openstack_dashboard import api
from openstack_dashboard.dashboards.project.loadbalancers import utils
AVAILABLE_PROTOCOLS = ('HTTP', 'HTTPS', 'TCP')
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(
initial="", required=False,
max_length=80, label=_("Description"))
# provider is optional because some LBaaS implementation does
# not support service-type extension.
provider = forms.ThemableChoiceField(label=_("Provider"), required=False)
subnet_id = forms.ThemableChoiceField(label=_("Subnet"))
protocol = forms.ThemableChoiceField(label=_("Protocol"))
lb_method = forms.ThemableChoiceField(label=_("Load Balancing Method"))
admin_state_up = forms.ThemableChoiceField(
choices=[(True, _('UP')),
(False, _('DOWN'))],
label=_("Admin State"))
def __init__(self, request, *args, **kwargs):
super(AddPoolAction, self).__init__(request, *args, **kwargs)
tenant_id = request.user.tenant_id
subnet_id_choices = [('', _("Select a Subnet"))]
try:
networks = api.neutron.network_list_for_tenant(request, tenant_id)
except Exception:
exceptions.handle(request,
_('Unable to retrieve networks list.'))
networks = []
for n in networks:
for s in n['subnets']:
name = "%s (%s)" % (s.name_or_id, s.cidr)
subnet_id_choices.append((s.id, name))
self.fields['subnet_id'].choices = subnet_id_choices
protocol_choices = [('', _("Select a Protocol"))]
[protocol_choices.append((p, p)) for p in AVAILABLE_PROTOCOLS]
self.fields['protocol'].choices = protocol_choices
lb_method_choices = [('', _("Select a Method"))]
[lb_method_choices.append((m, m)) for m in AVAILABLE_METHODS]
self.fields['lb_method'].choices = lb_method_choices
# provider choice
try:
if api.neutron.is_extension_supported(request, 'service-type'):
provider_list = api.neutron.provider_list(request)
providers = [p for p in provider_list
if p['service_type'] == 'LOADBALANCER']
else:
providers = None
except Exception:
exceptions.handle(request,
_('Unable to retrieve providers list.'))
providers = []
if providers:
default_providers = [p for p in providers if p.get('default')]
if default_providers:
default_provider = default_providers[0]['name']
else:
default_provider = None
provider_choices = [(p['name'], p['name']) for p in providers
if p['name'] != default_provider]
if default_provider:
provider_choices.insert(
0, (default_provider,
_("%s (default)") % default_provider))
else:
if providers is None:
msg = _("Provider for Load Balancer is not supported")
else:
msg = _("No provider is available")
provider_choices = [('', msg)]
self.fields['provider'].widget.attrs['readonly'] = True
self.fields['provider'].choices = provider_choices
class Meta(object):
name = _("Add New Pool")
permissions = ('openstack.services.network',)
help_text_template = 'project/loadbalancers/_create_pool_help.html'
class AddPoolStep(workflows.Step):
action_class = AddPoolAction
contributes = ("name", "description", "subnet_id", "provider",
"protocol", "lb_method", "admin_state_up")
def contribute(self, data, context):
context = super(AddPoolStep, self).contribute(data, context)
context['admin_state_up'] = (context['admin_state_up'] == 'True')
if data:
return context
class AddPool(workflows.Workflow):
slug = "addpool"
name = _("Add Pool")
finalize_button_name = _("Add")
success_message = _('Added pool "%s".')
failure_message = _('Unable to add pool "%s".')
success_url = "horizon:project:loadbalancers:index"
default_steps = (AddPoolStep,)
def format_status_message(self, message):
name = self.context.get('name')
return message % name
def handle(self, request, context):
try:
api.lbaas.pool_create(request, **context)
return True
except Exception:
return False
class AddVipAction(workflows.Action):
name = forms.CharField(max_length=80, label=_("Name"))
description = forms.CharField(
initial="", required=False,
max_length=80, label=_("Description"))
subnet_id = forms.ThemableChoiceField(label=_("VIP Subnet"),
initial="",
required=False)
address = forms.IPField(label=_("IP address"),
version=forms.IPv4 | forms.IPv6,
mask=False,
required=False)
protocol_port = forms.IntegerField(
label=_("Protocol Port"), min_value=1,
help_text=_("Enter an integer value "
"between 1 and 65535."),
validators=[validators.validate_port_range])
protocol = forms.ThemableChoiceField(label=_("Protocol"))
session_persistence = forms.ChoiceField(
required=False, initial={}, label=_("Session Persistence"),
widget=forms.ThemableSelectWidget(attrs={
'class': 'switchable',
'data-slug': 'persistence'
}))
cookie_name = forms.CharField(
initial="", required=False,
max_length=80, label=_("Cookie Name"),
help_text=_("Required for APP_COOKIE persistence;"
" Ignored otherwise."),
widget=forms.TextInput(attrs={
'class': 'switched',
'data-switch-on': 'persistence',
'data-persistence-app_cookie': 'APP_COOKIE',
}))
connection_limit = forms.IntegerField(
required=False, min_value=-1, label=_("Connection Limit"),
help_text=_("Maximum number of connections allowed "
"for the VIP or '-1' if the limit is not set"))
admin_state_up = forms.ThemableChoiceField(
choices=[(True, _('UP')),
(False, _('DOWN'))],
label=_("Admin State"))
def __init__(self, request, *args, **kwargs):
super(AddVipAction, self).__init__(request, *args, **kwargs)
tenant_id = request.user.tenant_id
subnet_id_choices = [('', _("Select a Subnet"))]
try:
networks = api.neutron.network_list_for_tenant(request, tenant_id)
except Exception:
exceptions.handle(request,
_('Unable to retrieve networks list.'))
networks = []
for n in networks:
for s in n['subnets']:
name = "%s (%s)" % (s.name, s.cidr)
subnet_id_choices.append((s.id, name))
self.fields['subnet_id'].choices = subnet_id_choices
protocol_choices = [('', _("Select a Protocol"))]
[protocol_choices.append((p, p)) for p in AVAILABLE_PROTOCOLS]
self.fields['protocol'].choices = protocol_choices
session_persistence_choices = [('', _("No Session Persistence"))]
for mode in ('SOURCE_IP', 'HTTP_COOKIE', 'APP_COOKIE'):
session_persistence_choices.append((mode.lower(), mode))
self.fields[
'session_persistence'].choices = session_persistence_choices
def clean(self):
cleaned_data = super(AddVipAction, self).clean()
persistence = cleaned_data.get('session_persistence')
if persistence:
cleaned_data['session_persistence'] = persistence.upper()
if (cleaned_data.get('session_persistence') == 'APP_COOKIE' and
not cleaned_data.get('cookie_name')):
msg = _('Cookie name is required for APP_COOKIE persistence.')
self._errors['cookie_name'] = self.error_class([msg])
return cleaned_data
class Meta(object):
name = _("Specify VIP")
permissions = ('openstack.services.network',)
help_text_template = 'project/loadbalancers/_create_vip_help.html'
class AddVipStep(workflows.Step):
action_class = AddVipAction
depends_on = ("pool_id", "subnet")
contributes = ("name", "description", "subnet_id",
"address", "protocol_port", "protocol",
"session_persistence", "cookie_name",
"connection_limit", "admin_state_up")
def contribute(self, data, context):
context = super(AddVipStep, self).contribute(data, context)
context['admin_state_up'] = (context['admin_state_up'] == 'True')
return context
class AddVip(workflows.Workflow):
slug = "addvip"
name = _("Add VIP")
finalize_button_name = _("Add")
success_message = _('Added VIP "%s".')
failure_message = _('Unable to add VIP "%s".')
success_url = "horizon:project:loadbalancers:index"
default_steps = (AddVipStep,)
def format_status_message(self, message):
name = self.context.get('name')
return message % name
def handle(self, request, context):
if context['subnet_id'] == '':
try:
pool = api.lbaas.pool_get(request, context['pool_id'])
context['subnet_id'] = pool['subnet_id']
except Exception:
context['subnet_id'] = None
self.failure_message = _(
'Unable to retrieve the specified pool. '
'Unable to add VIP "%s".')
return False
if context['session_persistence']:
stype = context['session_persistence']
if stype == 'APP_COOKIE':
cookie = context['cookie_name']
context['session_persistence'] = {'type': stype,
'cookie_name': cookie}
else:
context['session_persistence'] = {'type': stype}
else:
context['session_persistence'] = {}
try:
api.lbaas.vip_create(request, **context)
return True
except Exception:
return False
class AddMemberAction(workflows.Action):
pool_id = forms.ThemableChoiceField(label=_("Pool"))
member_type = forms.ChoiceField(
label=_("Member Source"),
choices=[('server_list', _("Select from active instances")),
('member_address', _("Specify member IP address"))],
required=False,
widget=forms.Select(attrs={
'class': 'switchable',
'data-slug': 'membertype'
}))
members = forms.MultipleChoiceField(
required=False,
initial=["default"],
widget=forms.SelectMultiple(attrs={
'class': 'switched',
'data-switch-on': 'membertype',
'data-membertype-server_list': _("Member Instance(s)"),
}),
help_text=_("Select members for this pool "))
address = forms.IPField(
required=False,
help_text=_("Specify member IP address"),
widget=forms.TextInput(attrs={
'class': 'switched',
'data-switch-on': 'membertype',
'data-membertype-member_address': _("Member Address"),
}),
initial="", version=forms.IPv4 | forms.IPv6, mask=False)
weight = forms.IntegerField(
max_value=256, min_value=1, label=_("Weight"), required=False,
help_text=_("Relative part of requests this pool member serves "
"compared to others. \nThe same weight will be applied to "
"all the selected members and can be modified later. "
"Weight must be in the range 1 to 256.")
)
protocol_port = forms.IntegerField(
label=_("Protocol Port"), min_value=1,
help_text=_("Enter an integer value between 1 and 65535. "
"The same port will be used for all the selected "
"members and can be modified later."),
validators=[validators.validate_port_range]
)
admin_state_up = forms.ThemableChoiceField(
choices=[(True, _('UP')),
(False, _('DOWN'))],
label=_("Admin State"))
def __init__(self, request, *args, **kwargs):
super(AddMemberAction, self).__init__(request, *args, **kwargs)
pool_id_choices = [('', _("Select a Pool"))]
try:
tenant_id = self.request.user.tenant_id
pools = api.lbaas.pool_list(request, tenant_id=tenant_id)
except Exception:
pools = []
exceptions.handle(request,
_('Unable to retrieve pools list.'))
pools = sorted(pools,
key=lambda pool: pool.name)
for p in pools:
pool_id_choices.append((p.id, p.name))
self.fields['pool_id'].choices = pool_id_choices
members_choices = []
try:
servers, has_more = api.nova.server_list(request)
except Exception:
servers = []
exceptions.handle(request,
_('Unable to retrieve instances list.'))
if len(servers) == 0:
self.fields['members'].widget.attrs[
'data-membertype-server_list'] = _(
"No servers available. To add a member, you "
"need at least one running instance.")
return
for m in servers:
members_choices.append((m.id, m.name))
self.fields['members'].choices = sorted(
members_choices,
key=lambda member: member[1])
def clean(self):
cleaned_data = super(AddMemberAction, self).clean()
if (cleaned_data.get('member_type') == 'server_list' and
not cleaned_data.get('members')):
msg = _('At least one member must be specified')
self._errors['members'] = self.error_class([msg])
elif (cleaned_data.get('member_type') == 'member_address' and
not cleaned_data.get('address')):
msg = _('Member IP address must be specified')
self._errors['address'] = self.error_class([msg])
return cleaned_data
class Meta(object):
name = _("Add New Member")
permissions = ('openstack.services.network',)
help_text = _("Add member(s) to the selected pool.\n\n"
"Choose one or more listed instances to be "
"added to the pool as member(s). "
"Assign a numeric weight and port number for the "
"selected member(s) to operate(s) on; e.g., 80. \n\n"
"Only one port can be associated with "
"each instance.")
class AddMemberStep(workflows.Step):
action_class = AddMemberAction
contributes = ("pool_id", "member_type", "members", "address",
"protocol_port", "weight", "admin_state_up")
def contribute(self, data, context):
context = super(AddMemberStep, self).contribute(data, context)
context['admin_state_up'] = (context['admin_state_up'] == 'True')
return context
class AddMember(workflows.Workflow):
slug = "addmember"
name = _("Add Member")
finalize_button_name = _("Add")
success_message = _('Added member(s).')
failure_message = _('Unable to add member(s)')
success_url = "horizon:project:loadbalancers:index"
default_steps = (AddMemberStep,)
def handle(self, request, context):
if context['member_type'] == 'server_list':
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
# 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.
if plist:
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
else:
self.failure_message = _('No ports available.')
return False
return True
else:
try:
context['member_id'] = api.lbaas.member_create(
request, **context).id
return True
except Exception as e:
msg = self.failure_message
LOG.info('%s: %s' % (msg, e))
return False
class AddMonitorAction(workflows.Action):
type = forms.ChoiceField(
label=_("Type"),
choices=[('ping', _('PING')),
('tcp', _('TCP')),
('http', _('HTTP')),
('https', _('HTTPS'))],
widget=forms.Select(attrs={
'class': 'switchable',
'data-slug': 'type'
}))
delay = forms.IntegerField(
min_value=1,
label=_("Delay"),
help_text=_("The minimum time in seconds between regular checks "
"of a member. It must be greater than or equal to "
"timeout"))
timeout = forms.IntegerField(
min_value=1,
label=_("Timeout"),
help_text=_("The maximum time in seconds for a monitor to wait "
"for a reply. It must be less than or equal to delay"))
max_retries = forms.IntegerField(
max_value=10, min_value=1,
label=_("Max Retries (1~10)"),
help_text=_("Number of permissible failures before changing "
"the status of member to inactive"))
http_method = forms.ChoiceField(
initial="GET",
required=False,
choices=[('GET', _('GET'))],
label=_("HTTP Method"),
help_text=_("HTTP method used to check health status of a member"),
widget=forms.Select(attrs={
'class': 'switched',
'data-switch-on': 'type',
'data-type-http': _('HTTP Method'),
'data-type-https': _('HTTP Method')
}))
url_path = forms.CharField(
initial="/",
required=False,
max_length=80,
label=_("URL"),
widget=forms.TextInput(attrs={
'class': 'switched',
'data-switch-on': 'type',
'data-type-http': _('URL'),
'data-type-https': _('URL')
}))
expected_codes = forms.RegexField(
initial="200",
required=False,
max_length=80,
regex=r'^(\d{3}(\s*,\s*\d{3})*)$|^(\d{3}-\d{3})$',
label=_("Expected HTTP Status Codes"),
help_text=_("Expected code may be a single value (e.g. 200), "
"a list of values (e.g. 200, 202), "
"or range of values (e.g. 200-204)"),
widget=forms.TextInput(attrs={
'class': 'switched',
'data-switch-on': 'type',
'data-type-http': _('Expected HTTP Status Codes'),
'data-type-https': _('Expected HTTP Status Codes')
}))
admin_state_up = forms.ThemableChoiceField(
choices=[(True, _('UP')),
(False, _('DOWN'))],
label=_("Admin State"))
def __init__(self, request, *args, **kwargs):
super(AddMonitorAction, self).__init__(request, *args, **kwargs)
def clean(self):
cleaned_data = super(AddMonitorAction, self).clean()
type_opt = cleaned_data.get('type')
delay = cleaned_data.get('delay')
timeout = cleaned_data.get('timeout')
if (delay is None) or (delay < timeout):
msg = _('Delay must be greater than or equal to Timeout')
self._errors['delay'] = self.error_class([msg])
if type_opt in ['http', 'https']:
http_method_opt = cleaned_data.get('http_method')
url_path = cleaned_data.get('url_path')
expected_codes = cleaned_data.get('expected_codes')
if not http_method_opt:
msg = _('Please choose a HTTP method')
self._errors['http_method'] = self.error_class([msg])
if not url_path:
msg = _('Please specify an URL')
self._errors['url_path'] = self.error_class([msg])
if not expected_codes:
msg = _('Please enter a single value (e.g. 200), '
'a list of values (e.g. 200, 202), '
'or range of values (e.g. 200-204)')
self._errors['expected_codes'] = self.error_class([msg])
return cleaned_data
class Meta(object):
name = _("Add New Monitor")
permissions = ('openstack.services.network',)
help_text = _("Create a monitor template.\n\n"
"Select type of monitoring. "
"Specify delay, timeout, and retry limits "
"required by the monitor. "
"Specify method, URL path, and expected "
"HTTP codes upon success.")
class AddMonitorStep(workflows.Step):
action_class = AddMonitorAction
contributes = ("type", "delay", "timeout", "max_retries",
"http_method", "url_path", "expected_codes",
"admin_state_up")
def contribute(self, data, context):
context = super(AddMonitorStep, self).contribute(data, context)
context['admin_state_up'] = (context['admin_state_up'] == 'True')
if data:
return context
class AddMonitor(workflows.Workflow):
slug = "addmonitor"
name = _("Add Monitor")
finalize_button_name = _("Add")
success_message = _('Added monitor')
failure_message = _('Unable to add monitor')
success_url = "horizon:project:loadbalancers:index"
default_steps = (AddMonitorStep,)
def handle(self, request, context):
try:
context['monitor_id'] = api.lbaas.pool_health_monitor_create(
request, **context).get('id')
return True
except Exception:
exceptions.handle(request, _("Unable to add monitor."))
return False
class AddPMAssociationAction(workflows.Action):
monitor_id = forms.ThemableChoiceField(label=_("Monitor"))
def __init__(self, request, *args, **kwargs):
super(AddPMAssociationAction, self).__init__(request, *args, **kwargs)
def populate_monitor_id_choices(self, request, context):
self.fields['monitor_id'].label = _("Select a monitor template "
"for %s") % context['pool_name']
monitor_id_choices = [('', _("Select a Monitor"))]
try:
tenant_id = self.request.user.tenant_id
monitors = api.lbaas.pool_health_monitor_list(request,
tenant_id=tenant_id)
pool_monitors_ids = [pm.id for pm in context['pool_monitors']]
for m in monitors:
if m.id not in pool_monitors_ids:
display_name = utils.get_monitor_display_name(m)
monitor_id_choices.append((m.id, display_name))
except Exception:
exceptions.handle(request,
_('Unable to retrieve monitors list.'))
self.fields['monitor_id'].choices = monitor_id_choices
return monitor_id_choices
class Meta(object):
name = _("Association Details")
permissions = ('openstack.services.network',)
help_text = _("Associate a health monitor with target pool.")
class AddPMAssociationStep(workflows.Step):
action_class = AddPMAssociationAction
depends_on = ("pool_id", "pool_name", "pool_monitors")
contributes = ("monitor_id",)
def contribute(self, data, context):
context = super(AddPMAssociationStep, self).contribute(data, context)
if data:
return context
class AddPMAssociation(workflows.Workflow):
slug = "addassociation"
name = _("Associate Monitor")
finalize_button_name = _("Associate")
success_message = _('Associated monitor.')
failure_message = _('Unable to associate monitor.')
success_url = "horizon:project:loadbalancers:index"
default_steps = (AddPMAssociationStep,)
def handle(self, request, context):
try:
context['monitor_id'] = api.lbaas.pool_monitor_association_create(
request, **context)
return True
except Exception:
exceptions.handle(request, _("Unable to associate monitor."))
return False
class DeletePMAssociationAction(workflows.Action):
monitor_id = forms.ThemableChoiceField(label=_("Monitor"))
def __init__(self, request, *args, **kwargs):
super(DeletePMAssociationAction, self).__init__(
request, *args, **kwargs)
def populate_monitor_id_choices(self, request, context):
self.fields['monitor_id'].label = (_("Select a health monitor of %s") %
context['pool_name'])
monitor_id_choices = [('', _("Select a Monitor"))]
try:
monitors = api.lbaas.pool_health_monitor_list(request)
pool_monitors_ids = [pm.id for pm in context['pool_monitors']]
for m in monitors:
if m.id in pool_monitors_ids:
display_name = utils.get_monitor_display_name(m)
monitor_id_choices.append((m.id, display_name))
except Exception:
exceptions.handle(request,
_('Unable to retrieve monitors list.'))
self.fields['monitor_id'].choices = monitor_id_choices
return monitor_id_choices
class Meta(object):
name = _("Association Details")
permissions = ('openstack.services.network',)
help_text = _("Disassociate a health monitor from target pool. ")
class DeletePMAssociationStep(workflows.Step):
action_class = DeletePMAssociationAction
depends_on = ("pool_id", "pool_name", "pool_monitors")
contributes = ("monitor_id",)
def contribute(self, data, context):
context = super(DeletePMAssociationStep, self).contribute(
data, context)
if data:
return context
class DeletePMAssociation(workflows.Workflow):
slug = "deleteassociation"
name = _("Disassociate Monitor")
finalize_button_name = _("Disassociate")
success_message = _('Disassociated monitor.')
failure_message = _('Unable to disassociate monitor.')
success_url = "horizon:project:loadbalancers:index"
default_steps = (DeletePMAssociationStep,)
def handle(self, request, context):
try:
context['monitor_id'] = api.lbaas.pool_monitor_association_delete(
request, **context)
return True
except Exception:
exceptions.handle(request, _("Unable to disassociate monitor."))
return False

View File

@ -83,8 +83,6 @@ resource_urls = {
'link': 'horizon:project:stacks:detail'},
"OS::Heat::WaitConditionHandle": {
'link': 'horizon:project:stacks:detail'},
"OS::Neutron::HealthMonitor": {
'link': 'horizon:project:loadbalancers:monitordetails'},
"OS::Neutron::IKEPolicy": {
'link': 'horizon:project:vpn:ikepolicydetails'},
"OS::Neutron::IPsecPolicy": {
@ -93,10 +91,6 @@ resource_urls = {
'link': 'horizon:project:vpn:ipsecsiteconnectiondetails'},
"OS::Neutron::Net": {
'link': 'horizon:project:networks:detail'},
"OS::Neutron::Pool": {
'link': 'horizon:project:loadbalancers:pooldetails'},
"OS::Neutron::PoolMember": {
'link': 'horizon:project:loadbalancers:memberdetails'},
"OS::Neutron::Port": {
'link': 'horizon:project:networks:ports:detail'},
"OS::Neutron::Router": {

View File

@ -1,10 +0,0 @@
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'loadbalancers'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'project'
# The slug of the panel group the PANEL is associated with.
PANEL_GROUP = 'network'
# Python panel class of the PANEL to be added.
ADD_PANEL = ('openstack_dashboard.dashboards.project.'
'loadbalancers.panel.LoadBalancer')

View File

@ -1,379 +0,0 @@
# 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 openstack_dashboard import api
from openstack_dashboard.test import helpers as test
from neutronclient.v2_0 import client
neutronclient = client.Client
class LbaasApiTests(test.APITestCase):
@test.create_stubs({neutronclient: ('create_vip',)})
def test_vip_create(self):
vip1 = self.api_vips.first()
form_data = {'address': vip1['address'],
'name': vip1['name'],
'description': vip1['description'],
'subnet_id': vip1['subnet_id'],
'protocol_port': vip1['protocol_port'],
'protocol': vip1['protocol'],
'pool_id': vip1['pool_id'],
'session_persistence': vip1['session_persistence'],
'connection_limit': vip1['connection_limit'],
'admin_state_up': vip1['admin_state_up']
}
vip = {'vip': self.api_vips.first()}
neutronclient.create_vip({'vip': form_data}).AndReturn(vip)
self.mox.ReplayAll()
ret_val = api.lbaas.vip_create(self.request, **form_data)
self.assertIsInstance(ret_val, api.lbaas.Vip)
@test.create_stubs({neutronclient: ('create_vip',)})
def test_vip_create_skip_address_if_empty(self):
vip1 = self.api_vips.first()
vipform_data = {'name': vip1['name'],
'description': vip1['description'],
'subnet_id': vip1['subnet_id'],
'protocol_port': vip1['protocol_port'],
'protocol': vip1['protocol'],
'pool_id': vip1['pool_id'],
'session_persistence': vip1['session_persistence'],
'connection_limit': vip1['connection_limit'],
'admin_state_up': vip1['admin_state_up']
}
neutronclient.create_vip({'vip': vipform_data}).AndReturn(
{'vip': vipform_data})
self.mox.ReplayAll()
form_data = dict(vipform_data)
form_data['address'] = ""
ret_val = api.lbaas.vip_create(self.request, **form_data)
self.assertIsInstance(ret_val, api.lbaas.Vip)
@test.create_stubs({neutronclient: ('list_vips',)})
def test_vip_list(self):
vips = {'vips': [{'id': 'abcdef-c3eb-4fee-9763-12de3338041e',
'address': '10.0.0.100',
'name': 'vip1name',
'description': 'vip1description',
'subnet_id': '12381d38-c3eb-4fee-9763-12de3338041e',
'protocol_port': '80',
'protocol': 'HTTP',
'pool_id': '8913dde8-4915-4b90-8d3e-b95eeedb0d49',
'connection_limit': '10',
'admin_state_up': True
}, ]}
neutronclient.list_vips().AndReturn(vips)
self.mox.ReplayAll()
ret_val = api.lbaas.vip_list(self.request)
for v in ret_val:
self.assertIsInstance(v, api.lbaas.Vip)
self.assertTrue(v.id)
@test.create_stubs({neutronclient: ('show_vip', 'show_pool'),
api.neutron: ('subnet_get', 'port_get')})
def test_vip_get(self):
vip = self.api_vips.first()
neutronclient.show_vip(vip['id']).AndReturn({'vip': vip})
api.neutron.subnet_get(self.request, vip['subnet_id']
).AndReturn(self.subnets.first())
api.neutron.port_get(self.request, vip['port_id']
).AndReturn(self.ports.first())
neutronclient.show_pool(vip['pool_id']
).AndReturn({'pool': self.api_pools.first()})
self.mox.ReplayAll()
ret_val = api.lbaas.vip_get(self.request, vip['id'])
self.assertIsInstance(ret_val, api.lbaas.Vip)
self.assertIsInstance(ret_val.subnet, api.neutron.Subnet)
self.assertEqual(vip['subnet_id'], ret_val.subnet.id)
self.assertIsInstance(ret_val.port, api.neutron.Port)
self.assertEqual(vip['port_id'], ret_val.port.id)
self.assertIsInstance(ret_val.pool, api.lbaas.Pool)
self.assertEqual(self.api_pools.first()['id'], ret_val.pool.id)
@test.create_stubs({neutronclient: ('update_vip',)})
def test_vip_update(self):
form_data = {'address': '10.0.0.100',
'name': 'vip1name',
'description': 'vip1description',
'subnet_id': '12381d38-c3eb-4fee-9763-12de3338041e',
'protocol_port': '80',
'protocol': 'HTTP',
'pool_id': '8913dde8-4915-4b90-8d3e-b95eeedb0d49',
'connection_limit': '10',
'admin_state_up': True
}
vip = {'vip': {'id': 'abcdef-c3eb-4fee-9763-12de3338041e',
'address': '10.0.0.100',
'name': 'vip1name',
'description': 'vip1description',
'subnet_id': '12381d38-c3eb-4fee-9763-12de3338041e',
'protocol_port': '80',
'protocol': 'HTTP',
'pool_id': '8913dde8-4915-4b90-8d3e-b95eeedb0d49',
'connection_limit': '10',
'admin_state_up': True
}}
neutronclient.update_vip(vip['vip']['id'], form_data).AndReturn(vip)
self.mox.ReplayAll()
ret_val = api.lbaas.vip_update(self.request,
vip['vip']['id'], **form_data)
self.assertIsInstance(ret_val, api.lbaas.Vip)
@test.create_stubs({neutronclient: ('create_pool',)})
def test_pool_create(self):
form_data = {'name': 'pool1name',
'description': 'pool1description',
'subnet_id': '12381d38-c3eb-4fee-9763-12de3338041e',
'protocol': 'HTTP',
'lb_method': 'ROUND_ROBIN',
'admin_state_up': True,
'provider': 'dummy'
}
pool = {'pool': {'id': 'abcdef-c3eb-4fee-9763-12de3338041e',
'name': 'pool1name',
'description': 'pool1description',
'subnet_id': '12381d38-c3eb-4fee-9763-12de3338041e',
'protocol': 'HTTP',
'lb_method': 'ROUND_ROBIN',
'admin_state_up': True,
'provider': 'dummy'
}}
neutronclient.create_pool({'pool': form_data}).AndReturn(pool)
self.mox.ReplayAll()
ret_val = api.lbaas.pool_create(self.request, **form_data)
self.assertIsInstance(ret_val, api.lbaas.Pool)
@test.create_stubs({neutronclient: ('list_pools', 'list_vips'),
api.neutron: ('subnet_list',)})
def test_pool_list(self):
pools = {'pools': self.api_pools.list()}
subnets = self.subnets.list()
vips = {'vips': self.api_vips.list()}
neutronclient.list_pools().AndReturn(pools)
api.neutron.subnet_list(self.request).AndReturn(subnets)
neutronclient.list_vips().AndReturn(vips)
self.mox.ReplayAll()
ret_val = api.lbaas.pool_list(self.request)
for v in ret_val:
self.assertIsInstance(v, api.lbaas.Pool)
self.assertTrue(v.id)
@test.create_stubs({neutronclient: ('show_pool', 'show_vip',
'list_members',
'show_health_monitor',),
api.neutron: ('subnet_get',)})
def test_pool_get(self):
pool = self.pools.first()
subnet = self.subnets.first()
pool_dict = {'pool': self.api_pools.first()}
vip_dict = {'vip': self.api_vips.first()}
neutronclient.show_pool(pool.id).AndReturn(pool_dict)
api.neutron.subnet_get(self.request, subnet.id).AndReturn(subnet)
neutronclient.show_vip(pool.vip_id).AndReturn(vip_dict)
neutronclient.list_members(pool_id=pool.id).AndReturn(
{'members': self.api_members.list()})
monitor = self.api_monitors.first()
for pool_mon in pool.health_monitors:
neutronclient.show_health_monitor(pool_mon).AndReturn(
{'health_monitor': monitor})
self.mox.ReplayAll()
ret_val = api.lbaas.pool_get(self.request, pool.id)
self.assertIsInstance(ret_val, api.lbaas.Pool)
self.assertIsInstance(ret_val.vip, api.lbaas.Vip)
self.assertEqual(ret_val.vip.id, vip_dict['vip']['id'])
self.assertIsInstance(ret_val.subnet, api.neutron.Subnet)
self.assertEqual(ret_val.subnet.id, subnet.id)
self.assertEqual(3, len(ret_val.members))
self.assertIsInstance(ret_val.members[0], api.lbaas.Member)
self.assertEqual(len(pool.health_monitors),
len(ret_val.health_monitors))
self.assertIsInstance(ret_val.health_monitors[0],
api.lbaas.PoolMonitor)
@test.create_stubs({neutronclient: ('update_pool',)})
def test_pool_update(self):
form_data = {'name': 'pool1name',
'description': 'pool1description',
'subnet_id': '12381d38-c3eb-4fee-9763-12de3338041e',
'protocol': 'HTTPS',
'lb_method': 'LEAST_CONNECTION',
'admin_state_up': True
}
pool = {'pool': {'id': 'abcdef-c3eb-4fee-9763-12de3338041e',
'name': 'pool1name',
'description': 'pool1description',
'subnet_id': '12381d38-c3eb-4fee-9763-12de3338041e',
'protocol': 'HTTPS',
'lb_method': 'LEAST_CONNECTION',
'admin_state_up': True
}}
neutronclient.update_pool(pool['pool']['id'],
form_data).AndReturn(pool)
self.mox.ReplayAll()
ret_val = api.lbaas.pool_update(self.request,
pool['pool']['id'], **form_data)
self.assertIsInstance(ret_val, api.lbaas.Pool)
@test.create_stubs({neutronclient: ('create_health_monitor',)})
def test_pool_health_monitor_create(self):
form_data = {'type': 'PING',
'delay': '10',
'timeout': '10',
'max_retries': '10',
'admin_state_up': True
}
monitor = {'health_monitor': {
'id': 'abcdef-c3eb-4fee-9763-12de3338041e',
'type': 'PING',
'delay': '10',
'timeout': '10',
'max_retries': '10',
'admin_state_up': True}}
neutronclient.create_health_monitor({
'health_monitor': form_data}).AndReturn(monitor)
self.mox.ReplayAll()
ret_val = api.lbaas.pool_health_monitor_create(
self.request, **form_data)
self.assertIsInstance(ret_val, api.lbaas.PoolMonitor)
@test.create_stubs({neutronclient: ('list_health_monitors',)})
def test_pool_health_monitor_list(self):
monitors = {'health_monitors': [
{'id': 'abcdef-c3eb-4fee-9763-12de3338041e',
'type': 'PING',
'delay': '10',
'timeout': '10',
'max_retries': '10',
'http_method': 'GET',
'url_path': '/monitor',
'expected_codes': '200',
'admin_state_up': True}, ]}
neutronclient.list_health_monitors().AndReturn(monitors)
self.mox.ReplayAll()
ret_val = api.lbaas.pool_health_monitor_list(self.request)
for v in ret_val:
self.assertIsInstance(v, api.lbaas.PoolMonitor)
self.assertTrue(v.id)
@test.create_stubs({neutronclient: ('show_health_monitor',
'list_pools')})
def test_pool_health_monitor_get(self):
monitor = self.api_monitors.first()
neutronclient.show_health_monitor(
monitor['id']).AndReturn({'health_monitor': monitor})
neutronclient.list_pools(id=[p['pool_id'] for p in monitor['pools']]
).AndReturn({'pools': self.api_pools.list()})
self.mox.ReplayAll()
ret_val = api.lbaas.pool_health_monitor_get(
self.request, monitor['id'])
self.assertIsInstance(ret_val, api.lbaas.PoolMonitor)
self.assertEqual(3, len(ret_val.pools))
self.assertIsInstance(ret_val.pools[0], api.lbaas.Pool)
@test.create_stubs({neutronclient: ('create_member', )})
def test_member_create(self):
form_data = {'pool_id': 'abcdef-c3eb-4fee-9763-12de3338041e',
'address': '10.0.1.2',
'protocol_port': '80',
'weight': '10',
'admin_state_up': True
}
member = {'member':
{'id': 'abcdef-c3eb-4fee-9763-12de3338041e',
'pool_id': 'abcdef-c3eb-4fee-9763-12de3338041e',
'address': '10.0.1.2',
'protocol_port': '80',
'weight': '10',
'admin_state_up': True}}
neutronclient.create_member({'member': form_data}).AndReturn(member)
self.mox.ReplayAll()
ret_val = api.lbaas.member_create(self.request, **form_data)
self.assertIsInstance(ret_val, api.lbaas.Member)
@test.create_stubs({neutronclient: ('list_members', 'list_pools')})
def test_member_list(self):
members = {'members': self.api_members.list()}
pools = {'pools': self.api_pools.list()}
neutronclient.list_members().AndReturn(members)
neutronclient.list_pools().AndReturn(pools)
self.mox.ReplayAll()
ret_val = api.lbaas.member_list(self.request)
for v in ret_val:
self.assertIsInstance(v, api.lbaas.Member)
self.assertTrue(v.id)
@test.create_stubs({neutronclient: ('show_member', 'show_pool')})
def test_member_get(self):
member = self.members.first()
member_dict = {'member': self.api_members.first()}
pool_dict = {'pool': self.api_pools.first()}
neutronclient.show_member(member.id).AndReturn(member_dict)
neutronclient.show_pool(member.pool_id).AndReturn(pool_dict)
self.mox.ReplayAll()
ret_val = api.lbaas.member_get(self.request, member.id)
self.assertIsInstance(ret_val, api.lbaas.Member)
@test.create_stubs({neutronclient: ('update_member',)})
def test_member_update(self):
form_data = {'pool_id': 'abcdef-c3eb-4fee-9763-12de3338041e',
'address': '10.0.1.4',
'protocol_port': '80',
'weight': '10',
'admin_state_up': True
}
member = {'member': {'id': 'abcdef-c3eb-4fee-9763-12de3338041e',
'pool_id': 'abcdef-c3eb-4fee-9763-12de3338041e',
'address': '10.0.1.2',
'protocol_port': '80',
'weight': '10',
'admin_state_up': True
}}
neutronclient.update_member(member['member']['id'],
form_data).AndReturn(member)
self.mox.ReplayAll()
ret_val = api.lbaas.member_update(self.request,
member['member']['id'], **form_data)
self.assertIsInstance(ret_val, api.lbaas.Member)

View File

@ -737,7 +737,6 @@ class NetworkApiNeutronFloatingIpTests(NetworkApiNeutronTestBase):
@override_settings(
OPENSTACK_NEUTRON_NETWORK={
'enable_lb': True,
'enable_fip_topology_check': True,
}
)
@ -758,8 +757,6 @@ class NetworkApiNeutronFloatingIpTests(NetworkApiNeutronTestBase):
filters = {'tenant_id': self.request.user.tenant_id}
# api.neutron.is_extension_supported(self.request, 'security-group'). \
# AndReturn(True)
# api.neutron.is_extension_supported(self.request, 'lbaas'). \
# AndReturn(True)
self.qclient.list_ports(**filters).AndReturn({'ports': ports})
servers = self.servers.list()
novaclient = self.stub_novaclient()
@ -779,7 +776,6 @@ class NetworkApiNeutronFloatingIpTests(NetworkApiNeutronTestBase):
shared_subs = [s for s in self.api_subnets.list()
if s['id'] in shared_subnet_ids]
self.qclient.list_subnets().AndReturn({'subnets': shared_subs})
self.qclient.list_vips().AndReturn({'vips': self.vips.list()})
self.mox.ReplayAll()

View File

@ -169,13 +169,12 @@ OPENSTACK_CINDER_FEATURES = {
OPENSTACK_NEUTRON_NETWORK = {
'enable_router': True,
'enable_quotas': False, # Enabled in specific tests only
# Parameters below (enable_lb, enable_firewall, enable_vpn)
# Parameters below (enable_firewall, enable_vpn)
# control if these panels are displayed or not,
# i.e. they only affect the navigation menu.
# These panels are registered even if enable_XXX is False,
# so we don't need to set them to True in most unit tests
# to avoid stubbing neutron extension check calls.
'enable_lb': False,
'enable_firewall': False,
'enable_vpn': False,
'profile_support': None,

View File

@ -17,7 +17,6 @@ import uuid
from openstack_dashboard.api import base
from openstack_dashboard.api import fwaas
from openstack_dashboard.api import lbaas
from openstack_dashboard.api import neutron
from openstack_dashboard.api import vpn
from openstack_dashboard.test.test_data import utils
@ -583,211 +582,6 @@ def data(TEST):
subnetpool = neutron.SubnetPool(subnetpool_dict)
TEST.subnetpools.add(subnetpool)
# LBaaS.
# 1st pool.
pool_dict = {'id': '8913dde8-4915-4b90-8d3e-b95eeedb0d49',
'tenant_id': '1',
'vip_id': 'abcdef-c3eb-4fee-9763-12de3338041e',
'name': 'pool1',
'description': 'pool description',
'subnet_id': TEST.subnets.first().id,
'protocol': 'HTTP',
'lb_method': 'ROUND_ROBIN',
'health_monitors': TEST.monitors.list(),
'members': ['78a46e5e-eb1a-418a-88c7-0e3f5968b08'],
'admin_state_up': True,
'status': 'ACTIVE',
'provider': 'haproxy'}
TEST.api_pools.add(pool_dict)
TEST.pools.add(lbaas.Pool(pool_dict))
# 2nd pool.
pool_dict = {'id': '8913dde8-4915-4b90-8d3e-b95eeedb0d50',
'tenant_id': '1',
'vip_id': 'f0881d38-c3eb-4fee-9763-12de3338041d',
'name': 'pool2',
'description': 'pool description',
'subnet_id': TEST.subnets.first().id,
'protocol': 'HTTPS',
'lb_method': 'ROUND_ROBIN',
'health_monitors': TEST.monitors.list()[0:1],
'members': [],
'status': 'PENDING_CREATE',
'admin_state_up': True}
TEST.api_pools.add(pool_dict)
TEST.pools.add(lbaas.Pool(pool_dict))
# 1st vip.
vip_dict = {'id': 'abcdef-c3eb-4fee-9763-12de3338041e',
'name': 'vip1',
'address': '10.0.0.100',
'description': 'vip description',
'subnet_id': TEST.subnets.first().id,
'port_id': TEST.ports.first().id,
'subnet': TEST.subnets.first().cidr,
'protocol_port': 80,
'protocol': pool_dict['protocol'],
'pool_id': pool_dict['id'],
'session_persistence': {'type': 'APP_COOKIE',
'cookie_name': 'jssessionid'},
'connection_limit': 10,
'admin_state_up': True}
TEST.api_vips.add(vip_dict)
TEST.vips.add(lbaas.Vip(vip_dict))
setattr(TEST.pools.first(), 'vip', TEST.vips.first())
# 2nd vip.
vip_dict = {'id': 'f0881d38-c3eb-4fee-9763-12de3338041d',
'name': 'vip2',
'address': '10.0.0.110',
'description': 'vip description',
'subnet_id': TEST.subnets.first().id,
'port_id': TEST.ports.list()[0].id,
'subnet': TEST.subnets.first().cidr,
'protocol_port': 80,
'protocol': pool_dict['protocol'],
'pool_id': pool_dict['id'],
'session_persistence': {'type': 'APP_COOKIE',
'cookie_name': 'jssessionid'},
'connection_limit': 10,
'admin_state_up': True}
TEST.api_vips.add(vip_dict)
TEST.vips.add(lbaas.Vip(vip_dict))
# 1st member.
member_dict = {'id': '78a46e5e-eb1a-418a-88c7-0e3f5968b08',
'tenant_id': '1',
'pool_id': pool_dict['id'],
'address': '10.0.0.11',
'protocol_port': 80,
'weight': 10,
'status': 'ACTIVE',
'admin_state_up': True}
TEST.api_members.add(member_dict)
TEST.members.add(lbaas.Member(member_dict))
# 2nd member.
member_dict = {'id': '41ac1f8d-6d9c-49a4-a1bf-41955e651f91',
'tenant_id': '1',
'pool_id': pool_dict['id'],
'address': '10.0.0.12',
'protocol_port': 80,
'weight': 10,
'status': 'ACTIVE',
'admin_state_up': True}
TEST.api_members.add(member_dict)
TEST.members.add(lbaas.Member(member_dict))
# 1st v6 pool.
pool_dict = {'id': 'c2983d70-8ac7-11e4-b116-123b93f75cba',
'tenant_id': '1',
'vip_id': 'b6598a5e-8ab4-11e4-b116-123b93f75cba',
'name': 'v6_pool1',
'description': 'pool description',
'subnet_id': TEST.subnets.get(name='v6_subnet1').id,
'protocol': 'HTTP',
'lb_method': 'ROUND_ROBIN',
'health_monitors': TEST.monitors.list(),
'members': ['78a46e5e-eb1a-418a-88c7-0e3f5968b08'],
'admin_state_up': True,
'status': 'ACTIVE',
'provider': 'haproxy'}
TEST.api_pools.add(pool_dict)
TEST.pools.add(lbaas.Pool(pool_dict))
# 1st v6 vip.
vip_dict = {'id': 'b6598a5e-8ab4-11e4-b116-123b93f75cba',
'name': 'v6_vip1',
'address': 'ff09::03',
'description': 'vip description',
'subnet_id': TEST.subnets.get(name="v6_subnet1").id,
'port_id': TEST.ports.first().id,
'subnet': TEST.subnets.get(name="v6_subnet1").cidr,
'protocol_port': 80,
'protocol': pool_dict['protocol'],
'pool_id': pool_dict['id'],
'session_persistence': {'type': 'APP_COOKIE',
'cookie_name': 'jssessionid'},
'connection_limit': 10,
'admin_state_up': True}
TEST.api_vips.add(vip_dict)
TEST.vips.add(lbaas.Vip(vip_dict))
# 2nd v6 vip.
vip_dict = {'id': 'b6598cc0-8ab4-11e4-b116-123b93f75cba',
'name': 'ff09::04',
'address': '10.0.0.110',
'description': 'vip description',
'subnet_id': TEST.subnets.get(name="v6_subnet2").id,
'port_id': TEST.ports.list()[0].id,
'subnet': TEST.subnets.get(name="v6_subnet2").cidr,
'protocol_port': 80,
'protocol': pool_dict['protocol'],
'pool_id': pool_dict['id'],
'session_persistence': {'type': 'APP_COOKIE',
'cookie_name': 'jssessionid'},
'connection_limit': 10,
'admin_state_up': True}
TEST.api_vips.add(vip_dict)
TEST.vips.add(lbaas.Vip(vip_dict))
# 1st v6 monitor.
monitor_dict = {'id': '0dc936f8-8aca-11e4-b116-123b93f75cba',
'type': 'http',
'delay': 10,
'timeout': 10,
'max_retries': 10,
'http_method': 'GET',
'url_path': '/',
'expected_codes': '200',
'admin_state_up': True,
"pools": [{"pool_id": TEST.pools.get(name='v6_pool1').id}],
}
TEST.api_monitors.add(monitor_dict)
TEST.monitors.add(lbaas.PoolMonitor(monitor_dict))
# v6 member.
member_dict = {'id': '6bc03d1e-8ad0-11e4-b116-123b93f75cba',
'tenant_id': '1',
'pool_id': TEST.pools.get(name='v6_pool1').id,
'address': 'ff09::03',
'protocol_port': 80,
'weight': 10,
'status': 'ACTIVE',
'member_type': 'server_list',
'admin_state_up': True}
TEST.api_members.add(member_dict)
TEST.members.add(lbaas.Member(member_dict))
# 1st monitor.
monitor_dict = {'id': 'd4a0500f-db2b-4cc4-afcf-ec026febff96',
'type': 'http',
'delay': 10,
'timeout': 10,
'max_retries': 10,
'http_method': 'GET',
'url_path': '/',
'expected_codes': '200',
'admin_state_up': True,
"pools": [{"pool_id": TEST.pools.list()[0].id},
{"pool_id": TEST.pools.list()[1].id}],
}
TEST.api_monitors.add(monitor_dict)
TEST.monitors.add(lbaas.PoolMonitor(monitor_dict))
# 2nd monitor.
monitor_dict = {'id': 'd4a0500f-db2b-4cc4-afcf-ec026febff97',
'type': 'ping',
'delay': 10,
'timeout': 10,
'max_retries': 10,
'admin_state_up': True,
'pools': [],
}
TEST.api_monitors.add(monitor_dict)
TEST.monitors.add(lbaas.PoolMonitor(monitor_dict))
# Quotas.
quota_data = {'network': '10',
'subnet': '10',
@ -828,15 +622,11 @@ def data(TEST):
extension_5 = {"name": "HA Router extension",
"alias": "l3-ha",
"description": "Add HA capability to routers."}
extension_6 = {"name": "LoadBalancing service",
"alias": "lbaas",
"description": "Extension for LoadBalancing service"}
TEST.api_extensions.add(extension_1)
TEST.api_extensions.add(extension_2)
TEST.api_extensions.add(extension_3)
TEST.api_extensions.add(extension_4)
TEST.api_extensions.add(extension_5)
TEST.api_extensions.add(extension_6)
# 1st agent.
agent_dict = {"binary": "neutron-openvswitch-agent",

View File

@ -0,0 +1,9 @@
---
upgrade:
- LBaaS v1 dashboard has been removed.
LBaaS v1 feature was removed from neutron-lbaas in Newton, but LBaaS v1
dashboard in Horizon has been kept only for backward compatibility in
Newton release so that operators can upgrade Horizon first.
Note that the Dashboard support for LBaaS v2 is provided as
a Horizon plugin via `neutron-lbaas-dashboard project
<http://git.openstack.org/cgit/openstack/neutron-lbaas-dashboard/>`__.