Merge "Quantum Floating IP support"
This commit is contained in:
commit
a366264d62
@ -36,6 +36,7 @@ from openstack_dashboard.api import base
|
||||
from openstack_dashboard.api import cinder
|
||||
from openstack_dashboard.api import glance
|
||||
from openstack_dashboard.api import keystone
|
||||
from openstack_dashboard.api import network
|
||||
from openstack_dashboard.api import nova
|
||||
from openstack_dashboard.api import quantum
|
||||
from openstack_dashboard.api import swift
|
||||
|
171
openstack_dashboard/api/network.py
Normal file
171
openstack_dashboard/api/network.py
Normal file
@ -0,0 +1,171 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2013 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.
|
||||
|
||||
"""Abstraction layer of networking functionalities.
|
||||
|
||||
Now Nova and Quantum have duplicated features.
|
||||
Thie API layer is introduced to hide the differences between them
|
||||
from dashboard implementations.
|
||||
"""
|
||||
|
||||
import abc
|
||||
|
||||
|
||||
class NetworkClient(object):
|
||||
def __init__(self, request):
|
||||
from openstack_dashboard import api
|
||||
if api.base.is_service_enabled(request, 'network'):
|
||||
self.floating_ips = api.quantum.FloatingIpManager(request)
|
||||
else:
|
||||
self.floating_ips = api.nova.FloatingIpManager(request)
|
||||
|
||||
|
||||
class FloatingIpManager(object):
|
||||
"""Abstract class to implement Floating IP methods
|
||||
|
||||
FloatingIP object returned from methods in this class
|
||||
must contains the following attributes:
|
||||
- id : ID of Floating IP
|
||||
- ip : Floating IP address
|
||||
- pool : ID of Floating IP pool from which the address is allocated
|
||||
- fixed_ip : Fixed IP address of a VIF associated with the address
|
||||
- port_id : ID of a VIF associated with the address
|
||||
(instance_id when Nova floating IP is used)
|
||||
- instance_id : Instance ID of an associated with the Floating IP
|
||||
"""
|
||||
|
||||
__metaclass__ = abc.ABCMeta
|
||||
|
||||
@abc.abstractmethod
|
||||
def list_pools(self):
|
||||
"""Fetches a list of all floating IP pools.
|
||||
|
||||
A list of FloatingIpPool object is returned.
|
||||
FloatingIpPool object is an APIResourceWrapper/APIDictWrapper
|
||||
where 'id' and 'name' attributes are defined.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def list(self):
|
||||
"""Fetches a list all floating IPs.
|
||||
|
||||
A returned value is a list of FloatingIp object.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get(self, floating_ip_id):
|
||||
"""Fetches the floating IP.
|
||||
|
||||
It returns a FloatingIp object corresponding to floating_ip_id.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def allocate(self, pool=None):
|
||||
"""Allocates a floating IP to the tenant.
|
||||
|
||||
You must provide a pool name or id for which you would like to
|
||||
allocate an floating IP.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def release(self, floating_ip_id):
|
||||
"""Releases a floating IP specified."""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def associate(self, floating_ip_id, port_id):
|
||||
"""Associates the floating IP to the port.
|
||||
|
||||
port_id is a fixed IP of a instance (Nova) or
|
||||
a port_id attached to a VNIC of a instance.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def disassociate(self, floating_ip_id, port_id):
|
||||
"""Disassociates the floating IP from the port.
|
||||
|
||||
port_id is a fixed IP of a instance (Nova) or
|
||||
a port_id attached to a VNIC of a instance.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def list_targets(self):
|
||||
"""Returns a list of association targets of instance VIFs.
|
||||
|
||||
Each association target is represented as FloatingIpTarget object.
|
||||
FloatingIpTarget is a APIResourceWrapper/APIDictWrapper and
|
||||
'id' and 'name' attributes must be defined in each object.
|
||||
FloatingIpTarget.id can be passed as port_id in associate().
|
||||
FloatingIpTarget.name is displayed in Floating Ip Association Form.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_target_id_by_instance(self, instance_id):
|
||||
"""Returns a target ID of floating IP association based on
|
||||
a backend implementation.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def is_simple_associate_supported(self):
|
||||
"""Returns True if the default floating IP pool is enabled."""
|
||||
pass
|
||||
|
||||
|
||||
def floating_ip_pools_list(request):
|
||||
return NetworkClient(request).floating_ips.list_pools()
|
||||
|
||||
|
||||
def tenant_floating_ip_list(request):
|
||||
return NetworkClient(request).floating_ips.list()
|
||||
|
||||
|
||||
def tenant_floating_ip_get(request, floating_ip_id):
|
||||
return NetworkClient(request).floating_ips.get(floating_ip_id)
|
||||
|
||||
|
||||
def tenant_floating_ip_allocate(request, pool=None):
|
||||
return NetworkClient(request).floating_ips.allocate(pool)
|
||||
|
||||
|
||||
def tenant_floating_ip_release(request, floating_ip_id):
|
||||
return NetworkClient(request).floating_ips.release(floating_ip_id)
|
||||
|
||||
|
||||
def floating_ip_associate(request, floating_ip_id, port_id):
|
||||
return NetworkClient(request).floating_ips.associate(floating_ip_id,
|
||||
port_id)
|
||||
|
||||
|
||||
def floating_ip_disassociate(request, floating_ip_id, port_id):
|
||||
return NetworkClient(request).floating_ips.disassociate(floating_ip_id,
|
||||
port_id)
|
||||
|
||||
|
||||
def floating_ip_target_list(request):
|
||||
return NetworkClient(request).floating_ips.list_targets()
|
||||
|
||||
|
||||
def floating_ip_target_get_by_instance(request, instance_id):
|
||||
return NetworkClient(request).floating_ips.get_target_id_by_instance(
|
||||
instance_id)
|
@ -32,10 +32,12 @@ from novaclient.v1_1 import security_group_rules as nova_rules
|
||||
from novaclient.v1_1.security_groups import SecurityGroup as NovaSecurityGroup
|
||||
from novaclient.v1_1.servers import REBOOT_HARD
|
||||
|
||||
from horizon.conf import HORIZON_CONFIG
|
||||
from horizon.utils.memoized import memoized
|
||||
|
||||
from openstack_dashboard.api.base import (APIResourceWrapper, QuotaSet,
|
||||
APIDictWrapper, url_for)
|
||||
from openstack_dashboard.api import network
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -182,6 +184,71 @@ class FlavorExtraSpec(object):
|
||||
self.value = val
|
||||
|
||||
|
||||
class FloatingIp(APIResourceWrapper):
|
||||
_attrs = ['id', 'ip', 'fixed_ip', 'port_id', 'instance_id', 'pool']
|
||||
|
||||
def __init__(self, fip):
|
||||
fip.__setattr__('port_id', fip.instance_id)
|
||||
super(FloatingIp, self).__init__(fip)
|
||||
|
||||
|
||||
class FloatingIpPool(APIDictWrapper):
|
||||
def __init__(self, pool):
|
||||
pool_dict = {'id': pool.name,
|
||||
'name': pool.name}
|
||||
super(FloatingIpPool, self).__init__(pool_dict)
|
||||
|
||||
|
||||
class FloatingIpTarget(APIDictWrapper):
|
||||
def __init__(self, server):
|
||||
server_dict = {'name': '%s (%s)' % (server.name, server.id),
|
||||
'id': server.id}
|
||||
super(FloatingIpTarget, self).__init__(server_dict)
|
||||
|
||||
|
||||
class FloatingIpManager(network.FloatingIpManager):
|
||||
def __init__(self, request):
|
||||
self.request = request
|
||||
self.client = novaclient(request)
|
||||
|
||||
def list_pools(self):
|
||||
return [FloatingIpPool(pool)
|
||||
for pool in self.client.floating_ip_pools.list()]
|
||||
|
||||
def list(self):
|
||||
return [FloatingIp(fip)
|
||||
for fip in self.client.floating_ips.list()]
|
||||
|
||||
def get(self, floating_ip_id):
|
||||
return FloatingIp(self.client.floating_ips.get(floating_ip_id))
|
||||
|
||||
def allocate(self, pool):
|
||||
return FloatingIp(self.client.floating_ips.create(pool=pool))
|
||||
|
||||
def release(self, floating_ip_id):
|
||||
self.client.floating_ips.delete(floating_ip_id)
|
||||
|
||||
def associate(self, floating_ip_id, port_id):
|
||||
# In Nova implied port_id is instance_id
|
||||
server = self.client.servers.get(port_id)
|
||||
fip = self.client.floating_ips.get(floating_ip_id)
|
||||
self.client.servers.add_floating_ip(server.id, fip.ip)
|
||||
|
||||
def disassociate(self, floating_ip_id, port_id):
|
||||
fip = self.client.floating_ips.get(floating_ip_id)
|
||||
server = self.client.servers.get(fip.instance_id)
|
||||
self.client.servers.remove_floating_ip(server.id, fip.ip)
|
||||
|
||||
def list_targets(self):
|
||||
return [FloatingIpTarget(s) for s in self.client.servers.list()]
|
||||
|
||||
def get_target_id_by_instance(self, instance_id):
|
||||
return instance_id
|
||||
|
||||
def is_simple_associate_supported(self):
|
||||
return HORIZON_CONFIG["simple_ip_management"]
|
||||
|
||||
|
||||
def novaclient(request):
|
||||
insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
|
||||
LOG.debug('novaclient connection created using token "%s" and url "%s"' %
|
||||
@ -255,33 +322,6 @@ def flavor_extra_set(request, flavor_id, metadata):
|
||||
return flavor.set_keys(metadata)
|
||||
|
||||
|
||||
def tenant_floating_ip_list(request):
|
||||
"""Fetches a list of all floating ips."""
|
||||
return novaclient(request).floating_ips.list()
|
||||
|
||||
|
||||
def floating_ip_pools_list(request):
|
||||
"""Fetches a list of all floating ip pools."""
|
||||
return novaclient(request).floating_ip_pools.list()
|
||||
|
||||
|
||||
def tenant_floating_ip_get(request, floating_ip_id):
|
||||
"""Fetches a floating ip."""
|
||||
return novaclient(request).floating_ips.get(floating_ip_id)
|
||||
|
||||
|
||||
def tenant_floating_ip_allocate(request, pool=None):
|
||||
"""Allocates a floating ip to tenant. Optionally you may provide a pool
|
||||
for which you would like the IP.
|
||||
"""
|
||||
return novaclient(request).floating_ips.create(pool=pool)
|
||||
|
||||
|
||||
def tenant_floating_ip_release(request, floating_ip_id):
|
||||
"""Releases floating ip from the pool of a tenant."""
|
||||
return novaclient(request).floating_ips.delete(floating_ip_id)
|
||||
|
||||
|
||||
def snapshot_create(request, instance_id, name):
|
||||
return novaclient(request).servers.create_image(instance_id, name)
|
||||
|
||||
@ -402,22 +442,6 @@ def server_revert_resize(request, instance_id):
|
||||
novaclient(request).servers.revert_resize(instance_id)
|
||||
|
||||
|
||||
def server_add_floating_ip(request, server, floating_ip):
|
||||
"""Associates floating IP to server's fixed IP.
|
||||
"""
|
||||
server = novaclient(request).servers.get(server)
|
||||
fip = novaclient(request).floating_ips.get(floating_ip)
|
||||
return novaclient(request).servers.add_floating_ip(server.id, fip.ip)
|
||||
|
||||
|
||||
def server_remove_floating_ip(request, server, floating_ip):
|
||||
"""Removes relationship between floating and server's fixed ip.
|
||||
"""
|
||||
fip = novaclient(request).floating_ips.get(floating_ip)
|
||||
server = novaclient(request).servers.get(fip.instance_id)
|
||||
return novaclient(request).servers.remove_floating_ip(server.id, fip.ip)
|
||||
|
||||
|
||||
def tenant_quota_get(request, tenant_id):
|
||||
return QuotaSet(novaclient(request).quotas.get(tenant_id))
|
||||
|
||||
|
@ -26,11 +26,17 @@ import logging
|
||||
from quantumclient.v2_0 import client as quantum_client
|
||||
from django.utils.datastructures import SortedDict
|
||||
|
||||
from horizon.conf import HORIZON_CONFIG
|
||||
|
||||
from openstack_dashboard.api.base import APIDictWrapper, url_for
|
||||
from openstack_dashboard.api import network
|
||||
from openstack_dashboard.api import nova
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
IP_VERSION_DICT = {4: 'IPv4', 6: 'IPv6'}
|
||||
|
||||
|
||||
class QuantumAPIDictWrapper(APIDictWrapper):
|
||||
|
||||
@ -87,7 +93,116 @@ class Router(QuantumAPIDictWrapper):
|
||||
super(Router, self).__init__(apiresource)
|
||||
|
||||
|
||||
IP_VERSION_DICT = {4: 'IPv4', 6: 'IPv6'}
|
||||
class FloatingIp(APIDictWrapper):
|
||||
_attrs = ['id', 'ip', 'fixed_ip', 'port_id', 'instance_id', 'pool']
|
||||
|
||||
def __init__(self, fip):
|
||||
fip['ip'] = fip['floating_ip_address']
|
||||
fip['fixed_ip'] = fip['fixed_ip_address']
|
||||
fip['pool'] = fip['floating_network_id']
|
||||
super(FloatingIp, self).__init__(fip)
|
||||
|
||||
|
||||
class FloatingIpPool(APIDictWrapper):
|
||||
pass
|
||||
|
||||
|
||||
class FloatingIpTarget(APIDictWrapper):
|
||||
pass
|
||||
|
||||
|
||||
class FloatingIpManager(network.FloatingIpManager):
|
||||
def __init__(self, request):
|
||||
self.request = request
|
||||
self.client = quantumclient(request)
|
||||
|
||||
def list_pools(self):
|
||||
search_opts = {'router:external': True}
|
||||
return [FloatingIpPool(pool) for pool
|
||||
in self.client.list_networks(**search_opts).get('networks')]
|
||||
|
||||
def list(self):
|
||||
fips = self.client.list_floatingips().get('floatingips')
|
||||
# Get port list to add instance_id to floating IP list
|
||||
# instance_id is stored in device_id attribute
|
||||
ports = port_list(self.request)
|
||||
device_id_dict = SortedDict([(p['id'], p['device_id']) for p in ports])
|
||||
for fip in fips:
|
||||
if fip['port_id']:
|
||||
fip['instance_id'] = device_id_dict[fip['port_id']]
|
||||
else:
|
||||
fip['instance_id'] = None
|
||||
return [FloatingIp(fip) for fip in fips]
|
||||
|
||||
def get(self, floating_ip_id):
|
||||
fip = self.client.show_floatingip(floating_ip_id).get('floatingip')
|
||||
if fip['port_id']:
|
||||
fip['instance_id'] = port_get(self.request,
|
||||
fip['port_id']).device_id
|
||||
else:
|
||||
fip['instance_id'] = None
|
||||
return FloatingIp(fip)
|
||||
|
||||
def allocate(self, pool):
|
||||
body = {'floatingip': {'floating_network_id': pool}}
|
||||
fip = self.client.create_floatingip(body).get('floatingip')
|
||||
fip['instance_id'] = None
|
||||
return FloatingIp(fip)
|
||||
|
||||
def release(self, floating_ip_id):
|
||||
self.client.delete_floatingip(floating_ip_id)
|
||||
|
||||
def associate(self, floating_ip_id, port_id):
|
||||
# NOTE: In Quantum Horizon floating IP support, port_id is
|
||||
# "<port_id>_<ip_address>" format to identify multiple ports.
|
||||
pid, ip_address = port_id.split('_', 1)
|
||||
update_dict = {'port_id': pid,
|
||||
'fixed_ip_address': ip_address}
|
||||
self.client.update_floatingip(floating_ip_id,
|
||||
{'floatingip': update_dict})
|
||||
|
||||
def disassociate(self, floating_ip_id, port_id):
|
||||
update_dict = {'port_id': None}
|
||||
self.client.update_floatingip(floating_ip_id,
|
||||
{'floatingip': update_dict})
|
||||
|
||||
def list_targets(self):
|
||||
ports = port_list(self.request)
|
||||
servers = nova.server_list(self.request)
|
||||
server_dict = SortedDict([(s.id, s.name) for s in servers])
|
||||
targets = []
|
||||
for p in ports:
|
||||
# Remove network ports from Floating IP targets
|
||||
if p.device_owner.startswith('network:'):
|
||||
continue
|
||||
port_id = p.id
|
||||
server_name = server_dict.get(p.device_id)
|
||||
for ip in p.fixed_ips:
|
||||
target = {'name': '%s: %s' % (server_name, ip['ip_address']),
|
||||
'id': '%s_%s' % (port_id, ip['ip_address'])}
|
||||
targets.append(FloatingIpTarget(target))
|
||||
return targets
|
||||
|
||||
def get_target_id_by_instance(self, instance_id):
|
||||
# In Quantum one port can have multiple ip addresses, so this method
|
||||
# picks up the first one and generate target id.
|
||||
if not instance_id:
|
||||
return None
|
||||
search_opts = {'device_id': instance_id}
|
||||
ports = port_list(self.request, **search_opts)
|
||||
if not ports:
|
||||
return None
|
||||
return '%s_%s' % (ports[0].id, ports[0].fixed_ips[0]['ip_address'])
|
||||
|
||||
def is_simple_associate_supported(self):
|
||||
# NOTE: There are two reason that simple association support
|
||||
# needs more considerations. (1) Quantum does not support the
|
||||
# default floating IP pool at the moment. It can be avoided
|
||||
# in case where only one floating IP pool exists.
|
||||
# (2) Quantum floating IP is associated with each VIF and
|
||||
# we need to check whether such VIF is only one for an instance
|
||||
# to enable simple association support.
|
||||
return False
|
||||
|
||||
|
||||
def get_ipver_str(ip_version):
|
||||
|
@ -38,7 +38,7 @@ class FloatingIpAllocate(forms.SelfHandlingForm):
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
fip = api.nova.tenant_floating_ip_allocate(request,
|
||||
fip = api.network.tenant_floating_ip_allocate(request,
|
||||
pool=data['pool'])
|
||||
messages.success(request,
|
||||
_('Allocated Floating IP %(ip)s.')
|
||||
|
@ -53,7 +53,7 @@ class ReleaseIPs(tables.BatchAction):
|
||||
classes = ('btn-danger', 'btn-release')
|
||||
|
||||
def action(self, request, obj_id):
|
||||
api.nova.tenant_floating_ip_release(request, obj_id)
|
||||
api.network.tenant_floating_ip_release(request, obj_id)
|
||||
|
||||
|
||||
class AssociateIP(tables.LinkAction):
|
||||
@ -63,7 +63,7 @@ class AssociateIP(tables.LinkAction):
|
||||
classes = ("ajax-modal", "btn-associate")
|
||||
|
||||
def allowed(self, request, fip):
|
||||
if fip.instance_id:
|
||||
if fip.port_id:
|
||||
return False
|
||||
return True
|
||||
|
||||
@ -79,15 +79,15 @@ class DisassociateIP(tables.Action):
|
||||
classes = ("btn-disassociate", "btn-danger")
|
||||
|
||||
def allowed(self, request, fip):
|
||||
if fip.instance_id:
|
||||
if fip.port_id:
|
||||
return True
|
||||
return False
|
||||
|
||||
def single(self, table, request, obj_id):
|
||||
try:
|
||||
fip = table.get_object_by_id(get_int_or_uuid(obj_id))
|
||||
api.nova.server_remove_floating_ip(request, fip.instance_id,
|
||||
fip.id)
|
||||
api.network.floating_ip_disassociate(request, fip.id,
|
||||
fip.port_id)
|
||||
LOG.info('Disassociating Floating IP "%s".' % obj_id)
|
||||
messages.success(request,
|
||||
_('Successfully disassociated Floating IP: %s')
|
||||
@ -116,7 +116,7 @@ class FloatingIPsTable(tables.DataTable):
|
||||
link=get_instance_link,
|
||||
verbose_name=_("Instance"),
|
||||
empty_value="-")
|
||||
pool = tables.Column("pool",
|
||||
pool = tables.Column("pool_name",
|
||||
verbose_name=_("Floating IP Pool"),
|
||||
empty_value="-")
|
||||
|
||||
|
@ -38,11 +38,11 @@ NAMESPACE = "horizon:project:access_and_security:floating_ips"
|
||||
|
||||
class FloatingIpViewTests(test.TestCase):
|
||||
def test_associate(self):
|
||||
self.mox.StubOutWithMock(api.nova, 'server_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_target_list')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||
api.network.floating_ip_target_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.servers.list())
|
||||
api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
self.mox.ReplayAll()
|
||||
|
||||
@ -58,17 +58,17 @@ class FloatingIpViewTests(test.TestCase):
|
||||
def test_associate_post(self):
|
||||
floating_ip = self.floating_ips.list()[1]
|
||||
server = self.servers.first()
|
||||
self.mox.StubOutWithMock(api.nova, 'server_add_floating_ip')
|
||||
self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'server_list')
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_associate')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_target_list')
|
||||
|
||||
api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
api.network.floating_ip_target_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.servers.list())
|
||||
api.nova.server_add_floating_ip(IsA(http.HttpRequest),
|
||||
server.id,
|
||||
floating_ip.id)
|
||||
api.network.floating_ip_associate(IsA(http.HttpRequest),
|
||||
floating_ip.id,
|
||||
server.id)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
form_data = {'instance_id': server.id,
|
||||
@ -80,17 +80,17 @@ class FloatingIpViewTests(test.TestCase):
|
||||
def test_associate_post_with_redirect(self):
|
||||
floating_ip = self.floating_ips.list()[1]
|
||||
server = self.servers.first()
|
||||
self.mox.StubOutWithMock(api.nova, 'server_add_floating_ip')
|
||||
self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'server_list')
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_associate')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_target_list')
|
||||
|
||||
api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
api.network.floating_ip_target_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.servers.list())
|
||||
api.nova.server_add_floating_ip(IsA(http.HttpRequest),
|
||||
server.id,
|
||||
floating_ip.id)
|
||||
api.network.floating_ip_associate(IsA(http.HttpRequest),
|
||||
floating_ip.id,
|
||||
server.id)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
form_data = {'instance_id': server.id,
|
||||
@ -103,17 +103,17 @@ class FloatingIpViewTests(test.TestCase):
|
||||
def test_associate_post_with_exception(self):
|
||||
floating_ip = self.floating_ips.list()[1]
|
||||
server = self.servers.first()
|
||||
self.mox.StubOutWithMock(api.nova, 'server_add_floating_ip')
|
||||
self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'server_list')
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_associate')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_target_list')
|
||||
|
||||
api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
api.network.floating_ip_target_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.servers.list())
|
||||
api.nova.server_add_floating_ip(IsA(http.HttpRequest),
|
||||
server.id,
|
||||
floating_ip.id) \
|
||||
api.network.floating_ip_associate(IsA(http.HttpRequest),
|
||||
floating_ip.id,
|
||||
server.id) \
|
||||
.AndRaise(self.exceptions.nova)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
@ -128,9 +128,9 @@ class FloatingIpViewTests(test.TestCase):
|
||||
server = self.servers.first()
|
||||
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'security_group_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_get')
|
||||
self.mox.StubOutWithMock(api.nova, 'server_remove_floating_ip')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_get')
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_disassociate')
|
||||
self.mox.StubOutWithMock(api.nova, 'server_list')
|
||||
|
||||
api.nova.server_list(IsA(http.HttpRequest),
|
||||
@ -139,11 +139,11 @@ class FloatingIpViewTests(test.TestCase):
|
||||
.AndReturn(self.keypairs.list())
|
||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.security_groups.list())
|
||||
api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.nova.server_remove_floating_ip(IsA(http.HttpRequest),
|
||||
server.id,
|
||||
floating_ip.id)
|
||||
api.network.floating_ip_disassociate(IsA(http.HttpRequest),
|
||||
floating_ip.id,
|
||||
server.id)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
action = "floating_ips__disassociate__%s" % floating_ip.id
|
||||
@ -156,9 +156,9 @@ class FloatingIpViewTests(test.TestCase):
|
||||
server = self.servers.first()
|
||||
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'security_group_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_get')
|
||||
self.mox.StubOutWithMock(api.nova, 'server_remove_floating_ip')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_get')
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_disassociate')
|
||||
self.mox.StubOutWithMock(api.nova, 'server_list')
|
||||
|
||||
api.nova.server_list(IsA(http.HttpRequest),
|
||||
@ -167,13 +167,13 @@ class FloatingIpViewTests(test.TestCase):
|
||||
.AndReturn(self.keypairs.list())
|
||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.security_groups.list())
|
||||
api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
|
||||
api.nova.server_remove_floating_ip(IsA(http.HttpRequest),
|
||||
server.id,
|
||||
floating_ip.id) \
|
||||
.AndRaise(self.exceptions.nova)
|
||||
api.network.floating_ip_disassociate(IsA(http.HttpRequest),
|
||||
floating_ip.id,
|
||||
server.id) \
|
||||
.AndRaise(self.exceptions.nova)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
action = "floating_ips__disassociate__%s" % floating_ip.id
|
||||
@ -184,8 +184,13 @@ class FloatingIpViewTests(test.TestCase):
|
||||
class FloatingIpQuantumViewTests(FloatingIpViewTests):
|
||||
def setUp(self):
|
||||
super(FloatingIpViewTests, self).setUp()
|
||||
self._floating_ips_orig = self.floating_ips
|
||||
self.floating_ips = self.floating_ips_uuid
|
||||
|
||||
def tearDown(self):
|
||||
self.floating_ips = self._floating_ips_orig
|
||||
super(FloatingIpViewTests, self).tearDown()
|
||||
|
||||
|
||||
class FloatingIpUtilsTests(test.TestCase):
|
||||
def test_accept_valid_integer(self):
|
||||
|
@ -59,12 +59,12 @@ class AllocateView(forms.ModalFormView):
|
||||
|
||||
def get_initial(self):
|
||||
try:
|
||||
pools = api.nova.floating_ip_pools_list(self.request)
|
||||
pools = api.network.floating_ip_pools_list(self.request)
|
||||
except:
|
||||
pools = []
|
||||
exceptions.handle(self.request,
|
||||
_("Unable to retrieve floating IP pools."))
|
||||
pool_list = [(pool.name, pool.name) for pool in pools]
|
||||
pool_list = [(pool.id, pool.name) for pool in pools]
|
||||
if not pool_list:
|
||||
pool_list = [(None, _("No floating IP pools available."))]
|
||||
return {'pool_list': pool_list}
|
||||
|
@ -42,15 +42,34 @@ class AssociateIPAction(workflows.Action):
|
||||
help_text = _("Select the IP address you wish to associate with "
|
||||
"the selected instance.")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AssociateIPAction, self).__init__(*args, **kwargs)
|
||||
if api.base.is_service_enabled(self.request, 'network'):
|
||||
label = _("Port to be associated")
|
||||
else:
|
||||
label = _("Instance to be associated")
|
||||
self.fields['instance_id'].label = label
|
||||
|
||||
# If AssociateIP is invoked from instance menu, instance_id parameter
|
||||
# is passed in URL. In Quantum based Floating IP implementation
|
||||
# an association target is not an instance but a port, so we need
|
||||
# to get an association target based on a received instance_id
|
||||
# and set the initial value of instance_id ChoiceField.
|
||||
q_instance_id = self.request.GET.get('instance_id')
|
||||
if q_instance_id:
|
||||
target_id = api.network.floating_ip_target_get_by_instance(
|
||||
self.request, q_instance_id)
|
||||
self.initial['instance_id'] = target_id
|
||||
|
||||
def populate_ip_id_choices(self, request, context):
|
||||
try:
|
||||
ips = api.nova.tenant_floating_ip_list(self.request)
|
||||
ips = api.network.tenant_floating_ip_list(self.request)
|
||||
except:
|
||||
redirect = reverse('horizon:project:access_and_security:index')
|
||||
exceptions.handle(self.request,
|
||||
_('Unable to retrieve floating IP addresses.'),
|
||||
redirect=redirect)
|
||||
options = sorted([(ip.id, ip.ip) for ip in ips if not ip.instance_id])
|
||||
options = sorted([(ip.id, ip.ip) for ip in ips if not ip.port_id])
|
||||
if options:
|
||||
options.insert(0, ("", _("Select an IP address")))
|
||||
else:
|
||||
@ -60,24 +79,32 @@ class AssociateIPAction(workflows.Action):
|
||||
|
||||
def populate_instance_id_choices(self, request, context):
|
||||
try:
|
||||
servers = api.nova.server_list(self.request)
|
||||
targets = api.network.floating_ip_target_list(self.request)
|
||||
except:
|
||||
redirect = reverse('horizon:project:access_and_security:index')
|
||||
exceptions.handle(self.request,
|
||||
_('Unable to retrieve instance list.'),
|
||||
redirect=redirect)
|
||||
instances = []
|
||||
for server in servers:
|
||||
server_name = "%s (%s)" % (server.name, server.id)
|
||||
instances.append((server.id, server_name))
|
||||
for target in targets:
|
||||
instances.append((target.id, target.name))
|
||||
|
||||
# Sort instances for easy browsing
|
||||
instances = sorted(instances, key=lambda x: x[1])
|
||||
|
||||
quantum_enabled = api.base.is_service_enabled(request, 'network')
|
||||
if instances:
|
||||
instances.insert(0, ("", _("Select an instance")))
|
||||
if quantum_enabled:
|
||||
label = _("Select a port")
|
||||
else:
|
||||
label = _("Select an instance")
|
||||
instances.insert(0, ("", label))
|
||||
else:
|
||||
instances = (("", _("No instances available")),)
|
||||
if quantum_enabled:
|
||||
label = _("No ports available")
|
||||
else:
|
||||
label = _("No instances available")
|
||||
instances = (("", label),)
|
||||
return instances
|
||||
|
||||
|
||||
@ -108,9 +135,9 @@ class IPAssociationWorkflow(workflows.Workflow):
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
api.nova.server_add_floating_ip(request,
|
||||
data['instance_id'],
|
||||
data['ip_id'])
|
||||
api.network.floating_ip_associate(request,
|
||||
data['ip_id'],
|
||||
data['instance_id'])
|
||||
except:
|
||||
exceptions.handle(request)
|
||||
return False
|
||||
|
@ -37,15 +37,15 @@ class KeyPairViewTests(test.TestCase):
|
||||
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'keypair_delete')
|
||||
self.mox.StubOutWithMock(api.nova, 'security_group_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'server_list')
|
||||
|
||||
api.nova.server_list(IsA(http.HttpRequest),
|
||||
all_tenants=True).AndReturn(self.servers.list())
|
||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.security_groups.list())
|
||||
api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
.AndReturn(self.security_groups.list())
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.nova.keypair_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.keypairs.list())
|
||||
api.nova.keypair_delete(IsA(http.HttpRequest), keypair.name)
|
||||
@ -60,15 +60,15 @@ class KeyPairViewTests(test.TestCase):
|
||||
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'keypair_delete')
|
||||
self.mox.StubOutWithMock(api.nova, 'security_group_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'server_list')
|
||||
|
||||
api.nova.server_list(IsA(http.HttpRequest),
|
||||
all_tenants=True).AndReturn(self.servers.list())
|
||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.security_groups.list())
|
||||
api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
.AndReturn(self.security_groups.list())
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.nova.keypair_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.keypairs.list())
|
||||
api.nova.keypair_delete(IsA(http.HttpRequest), keypair.name) \
|
||||
|
@ -30,11 +30,14 @@ from openstack_dashboard.test import helpers as test
|
||||
|
||||
|
||||
class AccessAndSecurityTests(test.TestCase):
|
||||
def setUp(self):
|
||||
super(AccessAndSecurityTests, self).setUp()
|
||||
|
||||
def test_index(self):
|
||||
keypairs = self.keypairs.list()
|
||||
sec_groups = self.security_groups.list()
|
||||
floating_ips = self.floating_ips.list()
|
||||
self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'security_group_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'server_list')
|
||||
@ -42,7 +45,7 @@ class AccessAndSecurityTests(test.TestCase):
|
||||
api.nova.server_list(IsA(http.HttpRequest),
|
||||
all_tenants=True).AndReturn(self.servers.list())
|
||||
api.nova.keypair_list(IsA(http.HttpRequest)).AndReturn(keypairs)
|
||||
api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(floating_ips)
|
||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(sec_groups)
|
||||
@ -60,21 +63,24 @@ class AccessAndSecurityTests(test.TestCase):
|
||||
floating_ips)
|
||||
|
||||
def test_association(self):
|
||||
servers = self.servers.list()
|
||||
|
||||
# Add duplicate instance name to test instance name with [IP]
|
||||
# change id and private IP
|
||||
servers = [api.nova.Server(s, self.request)
|
||||
for s in self.servers.list()]
|
||||
# Add duplicate instance name to test instance name with [ID]
|
||||
# Change id and private IP
|
||||
server3 = api.nova.Server(self.servers.first(), self.request)
|
||||
server3.id = 101
|
||||
server3.addresses = deepcopy(server3.addresses)
|
||||
server3.addresses['private'][0]['addr'] = "10.0.0.5"
|
||||
self.servers.add(server3)
|
||||
servers.append(server3)
|
||||
|
||||
self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.nova, 'server_list')
|
||||
api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
targets = [api.nova.FloatingIpTarget(s) for s in servers]
|
||||
|
||||
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||
self.mox.StubOutWithMock(api.network, 'floating_ip_target_list')
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.nova.server_list(IsA(http.HttpRequest)).AndReturn(servers)
|
||||
api.network.floating_ip_target_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(targets)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(reverse("horizon:project:access_and_security:"
|
||||
@ -89,7 +95,7 @@ class AccessAndSecurityTests(test.TestCase):
|
||||
self.assertContains(res, '<option value="2">server_2 (2)</option>')
|
||||
|
||||
|
||||
class AccessAndSecurityQuantumTests(AccessAndSecurityTests):
|
||||
class AccessAndSecurityQuantumProxyTests(AccessAndSecurityTests):
|
||||
def setUp(self):
|
||||
super(AccessAndSecurityTests, self).setUp()
|
||||
super(AccessAndSecurityQuantumProxyTests, self).setUp()
|
||||
self.floating_ips = self.floating_ips_uuid
|
||||
|
@ -27,9 +27,11 @@ import logging
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import messages
|
||||
from horizon import tables
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.api import network
|
||||
from openstack_dashboard.api import nova
|
||||
from .keypairs.tables import KeypairsTable
|
||||
from .floating_ips.tables import FloatingIPsTable
|
||||
from .security_groups.tables import SecurityGroupsTable
|
||||
@ -44,7 +46,7 @@ class IndexView(tables.MultiTableView):
|
||||
|
||||
def get_keypairs_data(self):
|
||||
try:
|
||||
keypairs = api.nova.keypair_list(self.request)
|
||||
keypairs = nova.keypair_list(self.request)
|
||||
except:
|
||||
keypairs = []
|
||||
exceptions.handle(self.request,
|
||||
@ -53,7 +55,7 @@ class IndexView(tables.MultiTableView):
|
||||
|
||||
def get_security_groups_data(self):
|
||||
try:
|
||||
security_groups = api.nova.security_group_list(self.request)
|
||||
security_groups = nova.security_group_list(self.request)
|
||||
except:
|
||||
security_groups = []
|
||||
exceptions.handle(self.request,
|
||||
@ -62,15 +64,23 @@ class IndexView(tables.MultiTableView):
|
||||
|
||||
def get_floating_ips_data(self):
|
||||
try:
|
||||
floating_ips = api.nova.tenant_floating_ip_list(self.request)
|
||||
floating_ips = network.tenant_floating_ip_list(self.request)
|
||||
except:
|
||||
floating_ips = []
|
||||
exceptions.handle(self.request,
|
||||
_('Unable to retrieve floating IP addresses.'))
|
||||
|
||||
try:
|
||||
floating_ip_pools = network.floating_ip_pools_list(self.request)
|
||||
except:
|
||||
floating_ip_pools = []
|
||||
messages.warning(self.request,
|
||||
_('Unable to retrieve floating IP pools.'))
|
||||
pool_dict = dict([(obj.id, obj.name) for obj in floating_ip_pools])
|
||||
|
||||
instances = []
|
||||
try:
|
||||
instances = api.nova.server_list(self.request, all_tenants=True)
|
||||
instances = nova.server_list(self.request, all_tenants=True)
|
||||
except:
|
||||
exceptions.handle(self.request,
|
||||
_('Unable to retrieve instance list.'))
|
||||
@ -80,5 +90,6 @@ class IndexView(tables.MultiTableView):
|
||||
for ip in floating_ips:
|
||||
ip.instance_name = instances_dict[ip.instance_id].name \
|
||||
if ip.instance_id in instances_dict else None
|
||||
ip.pool_name = pool_dict.get(ip.pool, ip.pool)
|
||||
|
||||
return floating_ips
|
||||
|
@ -276,7 +276,8 @@ class AssociateIP(tables.LinkAction):
|
||||
classes = ("ajax-modal", "btn-associate")
|
||||
|
||||
def allowed(self, request, instance):
|
||||
if HORIZON_CONFIG["simple_ip_management"]:
|
||||
fip = api.network.NetworkClient(request).floating_ips
|
||||
if fip.is_simple_associate_supported():
|
||||
return False
|
||||
return not is_deleting(instance)
|
||||
|
||||
@ -290,19 +291,20 @@ class AssociateIP(tables.LinkAction):
|
||||
|
||||
|
||||
class SimpleAssociateIP(tables.Action):
|
||||
name = "associate"
|
||||
name = "associate-simple"
|
||||
verbose_name = _("Associate Floating IP")
|
||||
classes = ("btn-associate",)
|
||||
classes = ("btn-associate-simple",)
|
||||
|
||||
def allowed(self, request, instance):
|
||||
if not HORIZON_CONFIG["simple_ip_management"]:
|
||||
fip = api.network.NetworkClient(request).floating_ips
|
||||
if not fip.is_simple_associate_supported():
|
||||
return False
|
||||
return not is_deleting(instance)
|
||||
|
||||
def single(self, table, request, instance):
|
||||
try:
|
||||
fip = api.nova.tenant_floating_ip_allocate(request)
|
||||
api.nova.server_add_floating_ip(request, instance, fip.id)
|
||||
fip = api.network.tenant_floating_ip_allocate(request)
|
||||
api.network.floating_ip_associate(request, fip.id, instance)
|
||||
messages.success(request,
|
||||
_("Successfully associated floating IP: %s")
|
||||
% fip.ip)
|
||||
@ -312,12 +314,6 @@ class SimpleAssociateIP(tables.Action):
|
||||
return shortcuts.redirect("horizon:project:instances:index")
|
||||
|
||||
|
||||
if HORIZON_CONFIG["simple_ip_management"]:
|
||||
CurrentAssociateIP = SimpleAssociateIP
|
||||
else:
|
||||
CurrentAssociateIP = AssociateIP
|
||||
|
||||
|
||||
class SimpleDisassociateIP(tables.Action):
|
||||
name = "disassociate"
|
||||
verbose_name = _("Disassociate Floating IP")
|
||||
@ -330,16 +326,15 @@ class SimpleDisassociateIP(tables.Action):
|
||||
|
||||
def single(self, table, request, instance_id):
|
||||
try:
|
||||
fips = [fip for fip in api.nova.tenant_floating_ip_list(request)
|
||||
if fip.instance_id == instance_id]
|
||||
fips = [fip for fip in api.network.tenant_floating_ip_list(request)
|
||||
if fip.port_id == instance_id]
|
||||
# Removing multiple floating IPs at once doesn't work, so this pops
|
||||
# off the first one.
|
||||
if fips:
|
||||
fip = fips.pop()
|
||||
api.nova.server_remove_floating_ip(request,
|
||||
instance_id,
|
||||
fip.id)
|
||||
api.nova.tenant_floating_ip_release(request, fip.id)
|
||||
api.network.floating_ip_disassociate(request,
|
||||
fip.id, instance_id)
|
||||
api.network.tenant_floating_ip_release(request, fip.id)
|
||||
messages.success(request,
|
||||
_("Successfully disassociated "
|
||||
"floating IP: %s") % fip.ip)
|
||||
@ -452,6 +447,7 @@ class InstancesTable(tables.DataTable):
|
||||
row_class = UpdateRow
|
||||
table_actions = (LaunchLink, TerminateInstance)
|
||||
row_actions = (ConfirmResize, RevertResize, CreateSnapshot,
|
||||
CurrentAssociateIP, SimpleDisassociateIP, EditInstance,
|
||||
SimpleAssociateIP, AssociateIP,
|
||||
SimpleDisassociateIP, EditInstance,
|
||||
ConsoleLink, LogLink, TogglePause, ToggleSuspend,
|
||||
RebootInstance, TerminateInstance)
|
||||
|
291
openstack_dashboard/test/api_tests/network_tests.py
Normal file
291
openstack_dashboard/test/api_tests/network_tests.py
Normal file
@ -0,0 +1,291 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2013 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 import http
|
||||
from mox import IsA
|
||||
|
||||
from novaclient.v1_1.floating_ip_pools import FloatingIPPool
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.test import helpers as test
|
||||
|
||||
|
||||
class NetworkApiNovaFloatingIpTests(test.APITestCase):
|
||||
def setUp(self):
|
||||
super(NetworkApiNovaFloatingIpTests, self).setUp()
|
||||
self.mox.StubOutWithMock(api.base, 'is_service_enabled')
|
||||
api.base.is_service_enabled(IsA(http.HttpRequest), 'network') \
|
||||
.AndReturn(False)
|
||||
|
||||
def test_floating_ip_pools_list(self):
|
||||
pool_names = ['pool1', 'pool2']
|
||||
pools = [FloatingIPPool(None, {'name': pool}) for pool in pool_names]
|
||||
novaclient = self.stub_novaclient()
|
||||
novaclient.floating_ip_pools = self.mox.CreateMockAnything()
|
||||
novaclient.floating_ip_pools.list().AndReturn(pools)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret = api.network.floating_ip_pools_list(self.request)
|
||||
self.assertEqual([p.name for p in ret], pool_names)
|
||||
|
||||
def test_floating_ip_list(self):
|
||||
fips = self.api_floating_ips.list()
|
||||
novaclient = self.stub_novaclient()
|
||||
novaclient.floating_ips = self.mox.CreateMockAnything()
|
||||
novaclient.floating_ips.list().AndReturn(fips)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret = api.network.tenant_floating_ip_list(self.request)
|
||||
for r, e in zip(ret, fips):
|
||||
for attr in ['id', 'ip', 'pool', 'fixed_ip', 'instance_id']:
|
||||
self.assertEqual(r.__getattr__(attr), e.__getattr__(attr))
|
||||
self.assertEqual(r.port_id, e.instance_id)
|
||||
|
||||
def test_floating_ip_get(self):
|
||||
fip = self.api_floating_ips.first()
|
||||
novaclient = self.stub_novaclient()
|
||||
novaclient.floating_ips = self.mox.CreateMockAnything()
|
||||
novaclient.floating_ips.get(fip.id).AndReturn(fip)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret = api.network.tenant_floating_ip_get(self.request, fip.id)
|
||||
for attr in ['id', 'ip', 'pool', 'fixed_ip', 'instance_id']:
|
||||
self.assertEqual(ret.__getattr__(attr), fip.__getattr__(attr))
|
||||
self.assertEqual(ret.port_id, fip.instance_id)
|
||||
|
||||
def test_floating_ip_allocate(self):
|
||||
pool_name = 'fip_pool'
|
||||
fip = self.api_floating_ips.first()
|
||||
novaclient = self.stub_novaclient()
|
||||
novaclient.floating_ips = self.mox.CreateMockAnything()
|
||||
novaclient.floating_ips.create(pool=pool_name).AndReturn(fip)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret = api.network.tenant_floating_ip_allocate(self.request, pool_name)
|
||||
for attr in ['id', 'ip', 'pool', 'fixed_ip', 'instance_id']:
|
||||
self.assertEqual(ret.__getattr__(attr), fip.__getattr__(attr))
|
||||
self.assertEqual(ret.port_id, fip.instance_id)
|
||||
|
||||
def test_floating_ip_release(self):
|
||||
fip = self.api_floating_ips.first()
|
||||
novaclient = self.stub_novaclient()
|
||||
novaclient.floating_ips = self.mox.CreateMockAnything()
|
||||
novaclient.floating_ips.delete(fip.id)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
api.network.tenant_floating_ip_release(self.request, fip.id)
|
||||
|
||||
def test_floating_ip_associate(self):
|
||||
server = api.nova.Server(self.servers.first(), self.request)
|
||||
floating_ip = self.floating_ips.first()
|
||||
|
||||
novaclient = self.stub_novaclient()
|
||||
novaclient.floating_ips = self.mox.CreateMockAnything()
|
||||
novaclient.servers = self.mox.CreateMockAnything()
|
||||
novaclient.servers.get(server.id).AndReturn(server)
|
||||
novaclient.floating_ips.get(floating_ip.id).AndReturn(floating_ip)
|
||||
novaclient.servers.add_floating_ip(server.id, floating_ip.ip) \
|
||||
.AndReturn(server)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
api.network.floating_ip_associate(self.request,
|
||||
floating_ip.id,
|
||||
server.id)
|
||||
|
||||
def test_floating_ip_disassociate(self):
|
||||
server = api.nova.Server(self.servers.first(), self.request)
|
||||
floating_ip = self.api_floating_ips.first()
|
||||
|
||||
novaclient = self.stub_novaclient()
|
||||
novaclient.servers = self.mox.CreateMockAnything()
|
||||
novaclient.floating_ips = self.mox.CreateMockAnything()
|
||||
novaclient.servers.get(server.id).AndReturn(server)
|
||||
novaclient.floating_ips.get(floating_ip.id).AndReturn(floating_ip)
|
||||
novaclient.servers.remove_floating_ip(server.id, floating_ip.ip) \
|
||||
.AndReturn(server)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
api.network.floating_ip_disassociate(self.request,
|
||||
floating_ip.id,
|
||||
server.id)
|
||||
|
||||
def test_floating_ip_target_list(self):
|
||||
servers = self.servers.list()
|
||||
novaclient = self.stub_novaclient()
|
||||
novaclient.servers = self.mox.CreateMockAnything()
|
||||
novaclient.servers.list().AndReturn(servers)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
targets = api.network.floating_ip_target_list(self.request)
|
||||
for target, server in zip(targets, servers):
|
||||
self.assertEqual(target.id, server.id)
|
||||
self.assertEqual(target.name, '%s (%s)' % (server.name, server.id))
|
||||
|
||||
def test_floating_ip_target_get_by_instance(self):
|
||||
self.mox.ReplayAll()
|
||||
instance_id = self.servers.first().id
|
||||
ret = api.network.floating_ip_target_get_by_instance(self.request,
|
||||
instance_id)
|
||||
self.assertEqual(instance_id, ret)
|
||||
|
||||
|
||||
class NetworkApiQuantumFloatingIpTests(test.APITestCase):
|
||||
def setUp(self):
|
||||
super(NetworkApiQuantumFloatingIpTests, self).setUp()
|
||||
self.mox.StubOutWithMock(api.base, 'is_service_enabled')
|
||||
api.base.is_service_enabled(IsA(http.HttpRequest), 'network') \
|
||||
.AndReturn(True)
|
||||
self.qclient = self.stub_quantumclient()
|
||||
|
||||
def test_floating_ip_pools_list(self):
|
||||
search_opts = {'router:external': True}
|
||||
ext_nets = [n for n in self.api_networks.list()
|
||||
if n['router:external']]
|
||||
self.qclient.list_networks(**search_opts) \
|
||||
.AndReturn({'networks': ext_nets})
|
||||
self.mox.ReplayAll()
|
||||
|
||||
rets = api.network.floating_ip_pools_list(self.request)
|
||||
for attr in ['id', 'name']:
|
||||
self.assertEqual([p.__getattr__(attr) for p in rets],
|
||||
[p[attr] for p in ext_nets])
|
||||
|
||||
def test_floating_ip_list(self):
|
||||
fips = self.api_q_floating_ips.list()
|
||||
self.qclient.list_floatingips().AndReturn({'floatingips': fips})
|
||||
self.qclient.list_ports().AndReturn({'ports': self.api_ports.list()})
|
||||
self.mox.ReplayAll()
|
||||
|
||||
rets = api.network.tenant_floating_ip_list(self.request)
|
||||
assoc_port = self.api_ports.list()[1]
|
||||
self.assertEqual(len(fips), len(rets))
|
||||
for ret, exp in zip(rets, fips):
|
||||
for attr in ['id', 'ip', 'pool', 'fixed_ip', 'port_id']:
|
||||
self.assertEqual(ret.__getattr__(attr), exp[attr])
|
||||
if exp['port_id']:
|
||||
dev_id = assoc_port['device_id'] if exp['port_id'] else None
|
||||
self.assertEqual(ret.instance_id, dev_id)
|
||||
|
||||
def test_floating_ip_get_associated(self):
|
||||
fip = self.api_q_floating_ips.list()[1]
|
||||
assoc_port = self.api_ports.list()[1]
|
||||
self.qclient.show_floatingip(fip['id']).AndReturn({'floatingip': fip})
|
||||
self.qclient.show_port(assoc_port['id']) \
|
||||
.AndReturn({'port': assoc_port})
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret = api.network.tenant_floating_ip_get(self.request, fip['id'])
|
||||
for attr in ['id', 'ip', 'pool', 'fixed_ip', 'port_id']:
|
||||
self.assertEqual(ret.__getattr__(attr), fip[attr])
|
||||
self.assertEqual(ret.instance_id, assoc_port['device_id'])
|
||||
|
||||
def test_floating_ip_get_unassociated(self):
|
||||
fip = self.api_q_floating_ips.list()[0]
|
||||
self.qclient.show_floatingip(fip['id']).AndReturn({'floatingip': fip})
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret = api.network.tenant_floating_ip_get(self.request, fip['id'])
|
||||
for attr in ['id', 'ip', 'pool', 'fixed_ip', 'port_id']:
|
||||
self.assertEqual(ret.__getattr__(attr), fip[attr])
|
||||
self.assertEqual(ret.instance_id, None)
|
||||
|
||||
def test_floating_ip_allocate(self):
|
||||
ext_nets = [n for n in self.api_networks.list()
|
||||
if n['router:external']]
|
||||
ext_net = ext_nets[0]
|
||||
fip = self.api_q_floating_ips.first()
|
||||
self.qclient.create_floatingip(
|
||||
{'floatingip': {'floating_network_id': ext_net['id']}}) \
|
||||
.AndReturn({'floatingip': fip})
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret = api.network.tenant_floating_ip_allocate(self.request,
|
||||
ext_net['id'])
|
||||
for attr in ['id', 'ip', 'pool', 'fixed_ip', 'port_id']:
|
||||
self.assertEqual(ret.__getattr__(attr), fip[attr])
|
||||
self.assertEqual(ret.instance_id, None)
|
||||
|
||||
def test_floating_ip_release(self):
|
||||
fip = self.api_q_floating_ips.first()
|
||||
self.qclient.delete_floatingip(fip['id'])
|
||||
self.mox.ReplayAll()
|
||||
|
||||
api.network.tenant_floating_ip_release(self.request, fip['id'])
|
||||
|
||||
def test_floating_ip_associate(self):
|
||||
fip = self.api_q_floating_ips.list()[1]
|
||||
assoc_port = self.api_ports.list()[1]
|
||||
ip_address = assoc_port['fixed_ips'][0]['ip_address']
|
||||
target_id = '%s_%s' % (assoc_port['id'], ip_address)
|
||||
params = {'port_id': assoc_port['id'],
|
||||
'fixed_ip_address': ip_address}
|
||||
self.qclient.update_floatingip(fip['id'],
|
||||
{'floatingip': params})
|
||||
self.mox.ReplayAll()
|
||||
|
||||
api.network.floating_ip_associate(self.request, fip['id'], target_id)
|
||||
|
||||
def test_floating_ip_disassociate(self):
|
||||
fip = self.api_q_floating_ips.list()[1]
|
||||
assoc_port = self.api_ports.list()[1]
|
||||
ip_address = assoc_port['fixed_ips'][0]['ip_address']
|
||||
target_id = '%s_%s' % (assoc_port['id'], ip_address)
|
||||
self.qclient.update_floatingip(fip['id'],
|
||||
{'floatingip': {'port_id': None}})
|
||||
self.mox.ReplayAll()
|
||||
|
||||
api.network.floating_ip_disassociate(self.request, fip['id'],
|
||||
target_id)
|
||||
|
||||
def _get_target_id(self, port):
|
||||
param = {'id': port['id'],
|
||||
'addr': port['fixed_ips'][0]['ip_address']}
|
||||
return '%(id)s_%(addr)s' % param
|
||||
|
||||
def _get_target_name(self, port):
|
||||
param = {'svrid': port['device_id'],
|
||||
'addr': port['fixed_ips'][0]['ip_address']}
|
||||
return 'server_%(svrid)s: %(addr)s' % param
|
||||
|
||||
def test_floating_ip_target_list(self):
|
||||
ports = self.api_ports.list()
|
||||
target_ports = [(self._get_target_id(p),
|
||||
self._get_target_name(p)) for p in ports
|
||||
if not p['device_owner'].startswith('network:')]
|
||||
|
||||
self.qclient.list_ports().AndReturn({'ports': ports})
|
||||
servers = self.servers.list()
|
||||
novaclient = self.stub_novaclient()
|
||||
novaclient.servers = self.mox.CreateMockAnything()
|
||||
search_opts = {'project_id': self.request.user.tenant_id}
|
||||
novaclient.servers.list(True, search_opts).AndReturn(servers)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
rets = api.network.floating_ip_target_list(self.request)
|
||||
self.assertEqual(len(rets), len(target_ports))
|
||||
for ret, exp in zip(rets, target_ports):
|
||||
self.assertEqual(ret.id, exp[0])
|
||||
self.assertEqual(ret.name, exp[1])
|
||||
|
||||
def test_floating_ip_target_get_by_instance(self):
|
||||
ports = self.api_ports.list()
|
||||
candidates = [p for p in ports if p['device_id'] == '1']
|
||||
search_opts = {'device_id': '1'}
|
||||
self.qclient.list_ports(**search_opts).AndReturn({'ports': candidates})
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret = api.network.floating_ip_target_get_by_instance(self.request, '1')
|
||||
self.assertEqual(ret, self._get_target_id(candidates[0]))
|
@ -138,42 +138,6 @@ class ComputeApiTests(test.APITestCase):
|
||||
ret_val = api.nova.server_get(self.request, server.id)
|
||||
self.assertIsInstance(ret_val, api.nova.Server)
|
||||
|
||||
def test_server_remove_floating_ip(self):
|
||||
server = api.nova.Server(self.servers.first(), self.request)
|
||||
floating_ip = self.floating_ips.first()
|
||||
|
||||
novaclient = self.stub_novaclient()
|
||||
novaclient.servers = self.mox.CreateMockAnything()
|
||||
novaclient.floating_ips = self.mox.CreateMockAnything()
|
||||
novaclient.servers.get(server.id).AndReturn(server)
|
||||
novaclient.floating_ips.get(floating_ip.id).AndReturn(floating_ip)
|
||||
novaclient.servers.remove_floating_ip(server.id, floating_ip.ip) \
|
||||
.AndReturn(server)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
server = api.nova.server_remove_floating_ip(self.request,
|
||||
server.id,
|
||||
floating_ip.id)
|
||||
self.assertIsInstance(server, api.nova.Server)
|
||||
|
||||
def test_server_add_floating_ip(self):
|
||||
server = api.nova.Server(self.servers.first(), self.request)
|
||||
floating_ip = self.floating_ips.first()
|
||||
novaclient = self.stub_novaclient()
|
||||
|
||||
novaclient.floating_ips = self.mox.CreateMockAnything()
|
||||
novaclient.servers = self.mox.CreateMockAnything()
|
||||
novaclient.servers.get(server.id).AndReturn(server)
|
||||
novaclient.floating_ips.get(floating_ip.id).AndReturn(floating_ip)
|
||||
novaclient.servers.add_floating_ip(server.id, floating_ip.ip) \
|
||||
.AndReturn(server)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
server = api.nova.server_add_floating_ip(self.request,
|
||||
server.id,
|
||||
floating_ip.id)
|
||||
self.assertIsInstance(server, api.nova.Server)
|
||||
|
||||
def test_absolute_limits_handle_unlimited(self):
|
||||
values = {"maxTotalCores": -1, "maxTotalInstances": 10}
|
||||
limits = self.mox.CreateMockAnything()
|
||||
|
@ -12,6 +12,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
import json
|
||||
import uuid
|
||||
|
||||
@ -23,6 +24,7 @@ from novaclient.v1_1 import (flavors, keypairs, servers, volumes,
|
||||
security_groups as sec_groups)
|
||||
|
||||
from openstack_dashboard.api.base import Quota, QuotaSet as QuotaSetWrapper
|
||||
from openstack_dashboard.api.nova import FloatingIp as NetFloatingIp
|
||||
from openstack_dashboard.usage.quotas import QuotaUsage
|
||||
from .utils import TestDataContainer
|
||||
|
||||
@ -150,6 +152,11 @@ def data(TEST):
|
||||
TEST.volume_snapshots = TestDataContainer()
|
||||
TEST.volume_types = TestDataContainer()
|
||||
|
||||
# Data return by novaclient.
|
||||
# It is used if API layer does data conversion.
|
||||
TEST.api_floating_ips = TestDataContainer()
|
||||
TEST.api_floating_ips_uuid = TestDataContainer()
|
||||
|
||||
# Volumes
|
||||
volume = volumes.Volume(volumes.VolumeManager(None),
|
||||
dict(id="41023e92-8008-4c8b-8059-7f2293ff3775",
|
||||
@ -356,26 +363,36 @@ def data(TEST):
|
||||
{'id': 1,
|
||||
'fixed_ip': '10.0.0.4',
|
||||
'instance_id': server_1.id,
|
||||
'ip': '58.58.58.58'})
|
||||
'ip': '58.58.58.58',
|
||||
'pool': 'pool1'})
|
||||
fip_2 = floating_ips.FloatingIP(floating_ips.FloatingIPManager(None),
|
||||
{'id': 2,
|
||||
'fixed_ip': None,
|
||||
'instance_id': None,
|
||||
'ip': '58.58.58.58'})
|
||||
TEST.floating_ips.add(fip_1, fip_2)
|
||||
'ip': '58.58.58.58',
|
||||
'pool': 'pool2'})
|
||||
TEST.api_floating_ips.add(fip_1, fip_2)
|
||||
|
||||
# Floating IP with UUID id (for Floating IP with Quantum)
|
||||
TEST.floating_ips.add(NetFloatingIp(copy.deepcopy(fip_1)),
|
||||
NetFloatingIp(copy.deepcopy(fip_2)))
|
||||
|
||||
# Floating IP with UUID id (for Floating IP with Quantum Proxy)
|
||||
fip_3 = floating_ips.FloatingIP(floating_ips.FloatingIPManager(None),
|
||||
{'id': str(uuid.uuid4()),
|
||||
'fixed_ip': '10.0.0.4',
|
||||
'instance_id': server_1.id,
|
||||
'ip': '58.58.58.58'})
|
||||
'ip': '58.58.58.58',
|
||||
'pool': 'pool1'})
|
||||
fip_4 = floating_ips.FloatingIP(floating_ips.FloatingIPManager(None),
|
||||
{'id': str(uuid.uuid4()),
|
||||
'fixed_ip': None,
|
||||
'instance_id': None,
|
||||
'ip': '58.58.58.58'})
|
||||
TEST.floating_ips_uuid.add(fip_3, fip_4)
|
||||
'ip': '58.58.58.58',
|
||||
'pool': 'pool2'})
|
||||
TEST.api_floating_ips_uuid.add(fip_3, fip_4)
|
||||
|
||||
TEST.floating_ips_uuid.add(NetFloatingIp(copy.deepcopy(fip_3)),
|
||||
NetFloatingIp(copy.deepcopy(fip_4)))
|
||||
|
||||
# Usage
|
||||
usage_vals = {"tenant_id": TEST.tenant.id,
|
||||
|
@ -14,7 +14,8 @@
|
||||
|
||||
import copy
|
||||
|
||||
from openstack_dashboard.api.quantum import Network, Subnet, Port, Router
|
||||
from openstack_dashboard.api.quantum import (Network, Subnet, Port,
|
||||
Router, FloatingIp)
|
||||
|
||||
from .utils import TestDataContainer
|
||||
|
||||
@ -25,13 +26,16 @@ def data(TEST):
|
||||
TEST.subnets = TestDataContainer()
|
||||
TEST.ports = TestDataContainer()
|
||||
TEST.routers = TestDataContainer()
|
||||
TEST.q_floating_ips = TestDataContainer()
|
||||
|
||||
# data return by quantumclient
|
||||
TEST.api_networks = TestDataContainer()
|
||||
TEST.api_subnets = TestDataContainer()
|
||||
TEST.api_ports = TestDataContainer()
|
||||
TEST.api_routers = TestDataContainer()
|
||||
TEST.api_q_floating_ips = TestDataContainer()
|
||||
|
||||
#------------------------------------------------------------
|
||||
# 1st network
|
||||
network_dict = {'admin_state_up': True,
|
||||
'id': '82288d84-e0a5-42ac-95be-e6af08727e42',
|
||||
@ -53,6 +57,17 @@ def data(TEST):
|
||||
'name': 'mysubnet1',
|
||||
'network_id': network_dict['id'],
|
||||
'tenant_id': network_dict['tenant_id']}
|
||||
|
||||
TEST.api_networks.add(network_dict)
|
||||
TEST.api_subnets.add(subnet_dict)
|
||||
|
||||
network = copy.deepcopy(network_dict)
|
||||
subnet = Subnet(subnet_dict)
|
||||
network['subnets'] = [subnet]
|
||||
TEST.networks.add(Network(network))
|
||||
TEST.subnets.add(subnet)
|
||||
|
||||
# ports on 1st network
|
||||
port_dict = {'admin_state_up': True,
|
||||
'device_id': 'af75c8e5-a1cc-4567-8d04-44fcd6922890',
|
||||
'device_owner': 'network:dhcp',
|
||||
@ -64,17 +79,25 @@ def data(TEST):
|
||||
'network_id': network_dict['id'],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': network_dict['tenant_id']}
|
||||
TEST.api_networks.add(network_dict)
|
||||
TEST.api_subnets.add(subnet_dict)
|
||||
TEST.api_ports.add(port_dict)
|
||||
|
||||
network = copy.deepcopy(network_dict)
|
||||
subnet = Subnet(subnet_dict)
|
||||
network['subnets'] = [subnet]
|
||||
TEST.networks.add(Network(network))
|
||||
TEST.subnets.add(subnet)
|
||||
TEST.ports.add(Port(port_dict))
|
||||
|
||||
port_dict = {'admin_state_up': True,
|
||||
'device_id': '1',
|
||||
'device_owner': 'compute:nova',
|
||||
'fixed_ips': [{'ip_address': '10.0.0.4',
|
||||
'subnet_id': subnet_dict['id']}],
|
||||
'id': '7e6ce62c-7ea2-44f8-b6b4-769af90a8406',
|
||||
'mac_address': 'fa:16:3e:9d:e6:2f',
|
||||
'name': '',
|
||||
'network_id': network_dict['id'],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': network_dict['tenant_id']}
|
||||
TEST.api_ports.add(port_dict)
|
||||
TEST.ports.add(Port(port_dict))
|
||||
assoc_port = port_dict
|
||||
|
||||
#------------------------------------------------------------
|
||||
# 2nd network
|
||||
network_dict = {'admin_state_up': True,
|
||||
'id': '72c3ab6c-c80f-4341-9dc5-210fa31ac6c2',
|
||||
@ -82,7 +105,7 @@ def data(TEST):
|
||||
'status': 'ACTIVE',
|
||||
'subnets': ['3f7c5d79-ee55-47b0-9213-8e669fb03009'],
|
||||
'tenant_id': '2',
|
||||
'router:external': True,
|
||||
'router:external': False,
|
||||
'shared': True}
|
||||
subnet_dict = {'allocation_pools': [{'end': '172.16.88.254',
|
||||
'start': '172.16.88.2'}],
|
||||
@ -99,28 +122,66 @@ def data(TEST):
|
||||
'name': 'aaaa',
|
||||
'network_id': network_dict['id'],
|
||||
'tenant_id': network_dict['tenant_id']}
|
||||
port_dict = {'admin_state_up': True,
|
||||
'device_id': '40e536b1-b9fd-4eb7-82d6-84db5d65a2ac',
|
||||
'device_owner': 'compute:nova',
|
||||
'fixed_ips': [{'ip_address': '172.16.88.3',
|
||||
'subnet_id': subnet_dict['id']}],
|
||||
'id': '7e6ce62c-7ea2-44f8-b6b4-769af90a8406',
|
||||
'mac_address': 'fa:16:3e:56:e6:2f',
|
||||
'name': '',
|
||||
'network_id': network_dict['id'],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': network_dict['tenant_id']}
|
||||
|
||||
TEST.api_networks.add(network_dict)
|
||||
TEST.api_subnets.add(subnet_dict)
|
||||
TEST.api_ports.add(port_dict)
|
||||
|
||||
network = copy.deepcopy(network_dict)
|
||||
subnet = Subnet(subnet_dict)
|
||||
network['subnets'] = [subnet]
|
||||
TEST.networks.add(Network(network))
|
||||
TEST.subnets.add(subnet)
|
||||
|
||||
port_dict = {'admin_state_up': True,
|
||||
'device_id': '2',
|
||||
'device_owner': 'compute:nova',
|
||||
'fixed_ips': [{'ip_address': '172.16.88.3',
|
||||
'subnet_id': subnet_dict['id']}],
|
||||
'id': '1db2cc37-3553-43fa-b7e2-3fc4eb4f9905',
|
||||
'mac_address': 'fa:16:3e:56:e6:2f',
|
||||
'name': '',
|
||||
'network_id': network_dict['id'],
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': network_dict['tenant_id']}
|
||||
|
||||
TEST.api_ports.add(port_dict)
|
||||
TEST.ports.add(Port(port_dict))
|
||||
|
||||
#------------------------------------------------------------
|
||||
# external network
|
||||
network_dict = {'admin_state_up': True,
|
||||
'id': '9b466b94-213a-4cda-badf-72c102a874da',
|
||||
'name': 'ext_net',
|
||||
'status': 'ACTIVE',
|
||||
'subnets': ['d6bdc71c-7566-4d32-b3ff-36441ce746e8'],
|
||||
'tenant_id': '3',
|
||||
'router:external': True,
|
||||
'shared': False}
|
||||
subnet_dict = {'allocation_pools': [{'start': '172.24.4.226.',
|
||||
'end': '172.24.4.238'}],
|
||||
'dns_nameservers': [],
|
||||
'host_routes': [],
|
||||
'cidr': '172.24.4.0/28',
|
||||
'enable_dhcp': False,
|
||||
'gateway_ip': '172.24.4.225',
|
||||
'id': 'd6bdc71c-7566-4d32-b3ff-36441ce746e8',
|
||||
'ip_version': 4,
|
||||
'name': 'ext_subnet',
|
||||
'network_id': network_dict['id'],
|
||||
'tenant_id': network_dict['tenant_id']}
|
||||
ext_net = network_dict
|
||||
ext_subnet = subnet_dict
|
||||
|
||||
TEST.api_networks.add(network_dict)
|
||||
TEST.api_subnets.add(subnet_dict)
|
||||
|
||||
network = copy.deepcopy(network_dict)
|
||||
subnet = Subnet(subnet_dict)
|
||||
network['subnets'] = [subnet]
|
||||
TEST.networks.add(Network(network))
|
||||
TEST.subnets.add(subnet)
|
||||
|
||||
#------------------------------------------------------------
|
||||
# Set up router data
|
||||
port_dict = {'admin_state_up': True,
|
||||
'device_id': '7180cede-bcd8-4334-b19f-f7ef2f331f53',
|
||||
@ -146,3 +207,27 @@ def data(TEST):
|
||||
'tenant_id': '1'}
|
||||
TEST.api_routers.add(router_dict)
|
||||
TEST.routers.add(Router(router_dict))
|
||||
|
||||
#------------------------------------------------------------
|
||||
# floating IP
|
||||
# unassociated
|
||||
fip_dict = {'tenant_id': '1',
|
||||
'floating_ip_address': '172.16.88.227',
|
||||
'floating_network_id': ext_net['id'],
|
||||
'id': '9012cd70-cfae-4e46-b71e-6a409e9e0063',
|
||||
'fixed_ip_address': None,
|
||||
'port_id': None,
|
||||
'router_id': None}
|
||||
TEST.api_q_floating_ips.add(fip_dict)
|
||||
TEST.q_floating_ips.add(FloatingIp(fip_dict))
|
||||
|
||||
# associated (with compute port on 1st network)
|
||||
fip_dict = {'tenant_id': '1',
|
||||
'floating_ip_address': '172.16.88.228',
|
||||
'floating_network_id': ext_net['id'],
|
||||
'id': 'a97af8f2-3149-4b97-abbd-e49ad19510f7',
|
||||
'fixed_ip_address': assoc_port['fixed_ips'][0]['ip_address'],
|
||||
'port_id': assoc_port['id'],
|
||||
'router_id': router_dict['id']}
|
||||
TEST.api_q_floating_ips.add(fip_dict)
|
||||
TEST.q_floating_ips.add(FloatingIp(fip_dict))
|
||||
|
@ -33,8 +33,8 @@ from openstack_dashboard.usage import quotas
|
||||
class QuotaTests(test.APITestCase):
|
||||
@test.create_stubs({api.nova: ('server_list',
|
||||
'flavor_list',
|
||||
'tenant_floating_ip_list',
|
||||
'tenant_quota_get',),
|
||||
api.network: ('tenant_floating_ip_list',),
|
||||
quotas: ('is_service_enabled',),
|
||||
cinder: ('volume_list', 'tenant_quota_get',)})
|
||||
def test_tenant_quota_usages(self):
|
||||
@ -44,7 +44,7 @@ class QuotaTests(test.APITestCase):
|
||||
.AndReturn(self.flavors.list())
|
||||
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||
.AndReturn(self.quotas.first())
|
||||
api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.servers.list())
|
||||
@ -73,8 +73,8 @@ class QuotaTests(test.APITestCase):
|
||||
|
||||
@test.create_stubs({api.nova: ('server_list',
|
||||
'flavor_list',
|
||||
'tenant_floating_ip_list',
|
||||
'tenant_quota_get',),
|
||||
api.network: ('tenant_floating_ip_list',),
|
||||
quotas: ('is_service_enabled',)})
|
||||
def test_tenant_quota_usages_without_volume(self):
|
||||
quotas.is_service_enabled(IsA(http.HttpRequest),
|
||||
@ -83,7 +83,7 @@ class QuotaTests(test.APITestCase):
|
||||
.AndReturn(self.flavors.list())
|
||||
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||
.AndReturn(self.quotas.first())
|
||||
api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.servers.list())
|
||||
@ -106,8 +106,8 @@ class QuotaTests(test.APITestCase):
|
||||
|
||||
@test.create_stubs({api.nova: ('server_list',
|
||||
'flavor_list',
|
||||
'tenant_floating_ip_list',
|
||||
'tenant_quota_get',),
|
||||
api.network: ('tenant_floating_ip_list',),
|
||||
quotas: ('is_service_enabled',)})
|
||||
def test_tenant_quota_usages_no_instances_running(self):
|
||||
quotas.is_service_enabled(IsA(http.HttpRequest),
|
||||
@ -116,7 +116,8 @@ class QuotaTests(test.APITestCase):
|
||||
.AndReturn(self.flavors.list())
|
||||
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||
.AndReturn(self.quotas.first())
|
||||
api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)).AndReturn([])
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn([])
|
||||
api.nova.server_list(IsA(http.HttpRequest)).AndReturn([])
|
||||
|
||||
self.mox.ReplayAll()
|
||||
@ -137,8 +138,8 @@ class QuotaTests(test.APITestCase):
|
||||
|
||||
@test.create_stubs({api.nova: ('server_list',
|
||||
'flavor_list',
|
||||
'tenant_floating_ip_list',
|
||||
'tenant_quota_get',),
|
||||
api.network: ('tenant_floating_ip_list',),
|
||||
quotas: ('is_service_enabled',),
|
||||
cinder: ('volume_list', 'tenant_quota_get',)})
|
||||
def test_tenant_quota_usages_unlimited_quota(self):
|
||||
@ -151,7 +152,7 @@ class QuotaTests(test.APITestCase):
|
||||
.AndReturn(self.flavors.list())
|
||||
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||
.AndReturn(inf_quota)
|
||||
api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
api.network.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.floating_ips.list())
|
||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.servers.list())
|
||||
|
@ -4,7 +4,7 @@ import itertools
|
||||
from horizon import exceptions
|
||||
from horizon.utils.memoized import memoized
|
||||
|
||||
from openstack_dashboard.api import nova, cinder
|
||||
from openstack_dashboard.api import nova, cinder, network
|
||||
from openstack_dashboard.api.base import is_service_enabled, QuotaSet
|
||||
|
||||
|
||||
@ -85,7 +85,7 @@ def tenant_quota_usages(request):
|
||||
usages.add_quota(quota)
|
||||
|
||||
# Get our usages.
|
||||
floating_ips = nova.tenant_floating_ip_list(request)
|
||||
floating_ips = network.tenant_floating_ip_list(request)
|
||||
flavors = dict([(f.id, f) for f in nova.flavor_list(request)])
|
||||
instances = nova.server_list(request)
|
||||
# Fetch deleted flavors if necessary.
|
||||
|
Loading…
Reference in New Issue
Block a user