Quantum Floating IP support
blueprint quantum-floating-ip This commit allows OpenStack dashboard users to use Quantum floating IP feature directly using Quantum API rather than Nova Proxy. By this users can associates a floating IP per virtual NIC. blueprint nova-net-quantum-abstraction This commit defines an abstract class in api/network.py. This class provides common interfaces related to network features duplicated in Nova and Quantum. A concrete class to handle operations should be defined in api/nova.py or api/quantum.py. Change-Id: I780356a9f41e72e32ce1877d390ac7f99e96899c
This commit is contained in:
parent
b6dac7c6c4
commit
dbfcc97e89
@ -36,6 +36,7 @@ from openstack_dashboard.api import base
|
|||||||
from openstack_dashboard.api import cinder
|
from openstack_dashboard.api import cinder
|
||||||
from openstack_dashboard.api import glance
|
from openstack_dashboard.api import glance
|
||||||
from openstack_dashboard.api import keystone
|
from openstack_dashboard.api import keystone
|
||||||
|
from openstack_dashboard.api import network
|
||||||
from openstack_dashboard.api import nova
|
from openstack_dashboard.api import nova
|
||||||
from openstack_dashboard.api import quantum
|
from openstack_dashboard.api import quantum
|
||||||
from openstack_dashboard.api import swift
|
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.security_groups import SecurityGroup as NovaSecurityGroup
|
||||||
from novaclient.v1_1.servers import REBOOT_HARD
|
from novaclient.v1_1.servers import REBOOT_HARD
|
||||||
|
|
||||||
|
from horizon.conf import HORIZON_CONFIG
|
||||||
from horizon.utils.memoized import memoized
|
from horizon.utils.memoized import memoized
|
||||||
|
|
||||||
from openstack_dashboard.api.base import (APIResourceWrapper, QuotaSet,
|
from openstack_dashboard.api.base import (APIResourceWrapper, QuotaSet,
|
||||||
APIDictWrapper, url_for)
|
APIDictWrapper, url_for)
|
||||||
|
from openstack_dashboard.api import network
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
@ -182,6 +184,71 @@ class FlavorExtraSpec(object):
|
|||||||
self.value = val
|
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):
|
def novaclient(request):
|
||||||
insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
|
insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
|
||||||
LOG.debug('novaclient connection created using token "%s" and url "%s"' %
|
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)
|
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):
|
def snapshot_create(request, instance_id, name):
|
||||||
return novaclient(request).servers.create_image(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)
|
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):
|
def tenant_quota_get(request, tenant_id):
|
||||||
return QuotaSet(novaclient(request).quotas.get(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 quantumclient.v2_0 import client as quantum_client
|
||||||
from django.utils.datastructures import SortedDict
|
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.base import APIDictWrapper, url_for
|
||||||
|
from openstack_dashboard.api import network
|
||||||
|
from openstack_dashboard.api import nova
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
IP_VERSION_DICT = {4: 'IPv4', 6: 'IPv6'}
|
||||||
|
|
||||||
|
|
||||||
class QuantumAPIDictWrapper(APIDictWrapper):
|
class QuantumAPIDictWrapper(APIDictWrapper):
|
||||||
|
|
||||||
@ -87,7 +93,116 @@ class Router(QuantumAPIDictWrapper):
|
|||||||
super(Router, self).__init__(apiresource)
|
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):
|
def get_ipver_str(ip_version):
|
||||||
|
@ -38,7 +38,7 @@ class FloatingIpAllocate(forms.SelfHandlingForm):
|
|||||||
|
|
||||||
def handle(self, request, data):
|
def handle(self, request, data):
|
||||||
try:
|
try:
|
||||||
fip = api.nova.tenant_floating_ip_allocate(request,
|
fip = api.network.tenant_floating_ip_allocate(request,
|
||||||
pool=data['pool'])
|
pool=data['pool'])
|
||||||
messages.success(request,
|
messages.success(request,
|
||||||
_('Allocated Floating IP %(ip)s.')
|
_('Allocated Floating IP %(ip)s.')
|
||||||
|
@ -53,7 +53,7 @@ class ReleaseIPs(tables.BatchAction):
|
|||||||
classes = ('btn-danger', 'btn-release')
|
classes = ('btn-danger', 'btn-release')
|
||||||
|
|
||||||
def action(self, request, obj_id):
|
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):
|
class AssociateIP(tables.LinkAction):
|
||||||
@ -63,7 +63,7 @@ class AssociateIP(tables.LinkAction):
|
|||||||
classes = ("ajax-modal", "btn-associate")
|
classes = ("ajax-modal", "btn-associate")
|
||||||
|
|
||||||
def allowed(self, request, fip):
|
def allowed(self, request, fip):
|
||||||
if fip.instance_id:
|
if fip.port_id:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -79,15 +79,15 @@ class DisassociateIP(tables.Action):
|
|||||||
classes = ("btn-disassociate", "btn-danger")
|
classes = ("btn-disassociate", "btn-danger")
|
||||||
|
|
||||||
def allowed(self, request, fip):
|
def allowed(self, request, fip):
|
||||||
if fip.instance_id:
|
if fip.port_id:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def single(self, table, request, obj_id):
|
def single(self, table, request, obj_id):
|
||||||
try:
|
try:
|
||||||
fip = table.get_object_by_id(get_int_or_uuid(obj_id))
|
fip = table.get_object_by_id(get_int_or_uuid(obj_id))
|
||||||
api.nova.server_remove_floating_ip(request, fip.instance_id,
|
api.network.floating_ip_disassociate(request, fip.id,
|
||||||
fip.id)
|
fip.port_id)
|
||||||
LOG.info('Disassociating Floating IP "%s".' % obj_id)
|
LOG.info('Disassociating Floating IP "%s".' % obj_id)
|
||||||
messages.success(request,
|
messages.success(request,
|
||||||
_('Successfully disassociated Floating IP: %s')
|
_('Successfully disassociated Floating IP: %s')
|
||||||
@ -116,7 +116,7 @@ class FloatingIPsTable(tables.DataTable):
|
|||||||
link=get_instance_link,
|
link=get_instance_link,
|
||||||
verbose_name=_("Instance"),
|
verbose_name=_("Instance"),
|
||||||
empty_value="-")
|
empty_value="-")
|
||||||
pool = tables.Column("pool",
|
pool = tables.Column("pool_name",
|
||||||
verbose_name=_("Floating IP Pool"),
|
verbose_name=_("Floating IP Pool"),
|
||||||
empty_value="-")
|
empty_value="-")
|
||||||
|
|
||||||
|
@ -38,11 +38,11 @@ NAMESPACE = "horizon:project:access_and_security:floating_ips"
|
|||||||
|
|
||||||
class FloatingIpViewTests(test.TestCase):
|
class FloatingIpViewTests(test.TestCase):
|
||||||
def test_associate(self):
|
def test_associate(self):
|
||||||
self.mox.StubOutWithMock(api.nova, 'server_list')
|
self.mox.StubOutWithMock(api.network, 'floating_ip_target_list')
|
||||||
self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
|
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_list')
|
||||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
api.network.floating_ip_target_list(IsA(http.HttpRequest)) \
|
||||||
.AndReturn(self.servers.list())
|
.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())
|
.AndReturn(self.floating_ips.list())
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
@ -58,17 +58,17 @@ class FloatingIpViewTests(test.TestCase):
|
|||||||
def test_associate_post(self):
|
def test_associate_post(self):
|
||||||
floating_ip = self.floating_ips.list()[1]
|
floating_ip = self.floating_ips.list()[1]
|
||||||
server = self.servers.first()
|
server = self.servers.first()
|
||||||
self.mox.StubOutWithMock(api.nova, 'server_add_floating_ip')
|
self.mox.StubOutWithMock(api.network, 'floating_ip_associate')
|
||||||
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')
|
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())
|
.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())
|
.AndReturn(self.servers.list())
|
||||||
api.nova.server_add_floating_ip(IsA(http.HttpRequest),
|
api.network.floating_ip_associate(IsA(http.HttpRequest),
|
||||||
server.id,
|
floating_ip.id,
|
||||||
floating_ip.id)
|
server.id)
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
form_data = {'instance_id': server.id,
|
form_data = {'instance_id': server.id,
|
||||||
@ -80,17 +80,17 @@ class FloatingIpViewTests(test.TestCase):
|
|||||||
def test_associate_post_with_redirect(self):
|
def test_associate_post_with_redirect(self):
|
||||||
floating_ip = self.floating_ips.list()[1]
|
floating_ip = self.floating_ips.list()[1]
|
||||||
server = self.servers.first()
|
server = self.servers.first()
|
||||||
self.mox.StubOutWithMock(api.nova, 'server_add_floating_ip')
|
self.mox.StubOutWithMock(api.network, 'floating_ip_associate')
|
||||||
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')
|
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())
|
.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())
|
.AndReturn(self.servers.list())
|
||||||
api.nova.server_add_floating_ip(IsA(http.HttpRequest),
|
api.network.floating_ip_associate(IsA(http.HttpRequest),
|
||||||
server.id,
|
floating_ip.id,
|
||||||
floating_ip.id)
|
server.id)
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
form_data = {'instance_id': server.id,
|
form_data = {'instance_id': server.id,
|
||||||
@ -103,17 +103,17 @@ class FloatingIpViewTests(test.TestCase):
|
|||||||
def test_associate_post_with_exception(self):
|
def test_associate_post_with_exception(self):
|
||||||
floating_ip = self.floating_ips.list()[1]
|
floating_ip = self.floating_ips.list()[1]
|
||||||
server = self.servers.first()
|
server = self.servers.first()
|
||||||
self.mox.StubOutWithMock(api.nova, 'server_add_floating_ip')
|
self.mox.StubOutWithMock(api.network, 'floating_ip_associate')
|
||||||
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')
|
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())
|
.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())
|
.AndReturn(self.servers.list())
|
||||||
api.nova.server_add_floating_ip(IsA(http.HttpRequest),
|
api.network.floating_ip_associate(IsA(http.HttpRequest),
|
||||||
server.id,
|
floating_ip.id,
|
||||||
floating_ip.id) \
|
server.id) \
|
||||||
.AndRaise(self.exceptions.nova)
|
.AndRaise(self.exceptions.nova)
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
@ -128,9 +128,9 @@ class FloatingIpViewTests(test.TestCase):
|
|||||||
server = self.servers.first()
|
server = self.servers.first()
|
||||||
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
||||||
self.mox.StubOutWithMock(api.nova, 'security_group_list')
|
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, 'tenant_floating_ip_get')
|
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_get')
|
||||||
self.mox.StubOutWithMock(api.nova, 'server_remove_floating_ip')
|
self.mox.StubOutWithMock(api.network, 'floating_ip_disassociate')
|
||||||
self.mox.StubOutWithMock(api.nova, 'server_list')
|
self.mox.StubOutWithMock(api.nova, 'server_list')
|
||||||
|
|
||||||
api.nova.server_list(IsA(http.HttpRequest),
|
api.nova.server_list(IsA(http.HttpRequest),
|
||||||
@ -139,11 +139,11 @@ class FloatingIpViewTests(test.TestCase):
|
|||||||
.AndReturn(self.keypairs.list())
|
.AndReturn(self.keypairs.list())
|
||||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||||
.AndReturn(self.security_groups.list())
|
.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())
|
.AndReturn(self.floating_ips.list())
|
||||||
api.nova.server_remove_floating_ip(IsA(http.HttpRequest),
|
api.network.floating_ip_disassociate(IsA(http.HttpRequest),
|
||||||
server.id,
|
floating_ip.id,
|
||||||
floating_ip.id)
|
server.id)
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
action = "floating_ips__disassociate__%s" % floating_ip.id
|
action = "floating_ips__disassociate__%s" % floating_ip.id
|
||||||
@ -156,9 +156,9 @@ class FloatingIpViewTests(test.TestCase):
|
|||||||
server = self.servers.first()
|
server = self.servers.first()
|
||||||
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
||||||
self.mox.StubOutWithMock(api.nova, 'security_group_list')
|
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, 'tenant_floating_ip_get')
|
self.mox.StubOutWithMock(api.network, 'tenant_floating_ip_get')
|
||||||
self.mox.StubOutWithMock(api.nova, 'server_remove_floating_ip')
|
self.mox.StubOutWithMock(api.network, 'floating_ip_disassociate')
|
||||||
self.mox.StubOutWithMock(api.nova, 'server_list')
|
self.mox.StubOutWithMock(api.nova, 'server_list')
|
||||||
|
|
||||||
api.nova.server_list(IsA(http.HttpRequest),
|
api.nova.server_list(IsA(http.HttpRequest),
|
||||||
@ -167,12 +167,12 @@ class FloatingIpViewTests(test.TestCase):
|
|||||||
.AndReturn(self.keypairs.list())
|
.AndReturn(self.keypairs.list())
|
||||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||||
.AndReturn(self.security_groups.list())
|
.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())
|
.AndReturn(self.floating_ips.list())
|
||||||
|
|
||||||
api.nova.server_remove_floating_ip(IsA(http.HttpRequest),
|
api.network.floating_ip_disassociate(IsA(http.HttpRequest),
|
||||||
server.id,
|
floating_ip.id,
|
||||||
floating_ip.id) \
|
server.id) \
|
||||||
.AndRaise(self.exceptions.nova)
|
.AndRaise(self.exceptions.nova)
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
@ -184,8 +184,13 @@ class FloatingIpViewTests(test.TestCase):
|
|||||||
class FloatingIpQuantumViewTests(FloatingIpViewTests):
|
class FloatingIpQuantumViewTests(FloatingIpViewTests):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(FloatingIpViewTests, self).setUp()
|
super(FloatingIpViewTests, self).setUp()
|
||||||
|
self._floating_ips_orig = self.floating_ips
|
||||||
self.floating_ips = self.floating_ips_uuid
|
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):
|
class FloatingIpUtilsTests(test.TestCase):
|
||||||
def test_accept_valid_integer(self):
|
def test_accept_valid_integer(self):
|
||||||
|
@ -59,12 +59,12 @@ class AllocateView(forms.ModalFormView):
|
|||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
try:
|
try:
|
||||||
pools = api.nova.floating_ip_pools_list(self.request)
|
pools = api.network.floating_ip_pools_list(self.request)
|
||||||
except:
|
except:
|
||||||
pools = []
|
pools = []
|
||||||
exceptions.handle(self.request,
|
exceptions.handle(self.request,
|
||||||
_("Unable to retrieve floating IP pools."))
|
_("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:
|
if not pool_list:
|
||||||
pool_list = [(None, _("No floating IP pools available."))]
|
pool_list = [(None, _("No floating IP pools available."))]
|
||||||
return {'pool_list': pool_list}
|
return {'pool_list': pool_list}
|
||||||
|
@ -42,15 +42,34 @@ class AssociateIPAction(workflows.Action):
|
|||||||
help_text = _("Select the IP address you wish to associate with "
|
help_text = _("Select the IP address you wish to associate with "
|
||||||
"the selected instance.")
|
"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):
|
def populate_ip_id_choices(self, request, context):
|
||||||
try:
|
try:
|
||||||
ips = api.nova.tenant_floating_ip_list(self.request)
|
ips = api.network.tenant_floating_ip_list(self.request)
|
||||||
except:
|
except:
|
||||||
redirect = reverse('horizon:project:access_and_security:index')
|
redirect = reverse('horizon:project:access_and_security:index')
|
||||||
exceptions.handle(self.request,
|
exceptions.handle(self.request,
|
||||||
_('Unable to retrieve floating IP addresses.'),
|
_('Unable to retrieve floating IP addresses.'),
|
||||||
redirect=redirect)
|
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:
|
if options:
|
||||||
options.insert(0, ("", _("Select an IP address")))
|
options.insert(0, ("", _("Select an IP address")))
|
||||||
else:
|
else:
|
||||||
@ -60,24 +79,32 @@ class AssociateIPAction(workflows.Action):
|
|||||||
|
|
||||||
def populate_instance_id_choices(self, request, context):
|
def populate_instance_id_choices(self, request, context):
|
||||||
try:
|
try:
|
||||||
servers = api.nova.server_list(self.request)
|
targets = api.network.floating_ip_target_list(self.request)
|
||||||
except:
|
except:
|
||||||
redirect = reverse('horizon:project:access_and_security:index')
|
redirect = reverse('horizon:project:access_and_security:index')
|
||||||
exceptions.handle(self.request,
|
exceptions.handle(self.request,
|
||||||
_('Unable to retrieve instance list.'),
|
_('Unable to retrieve instance list.'),
|
||||||
redirect=redirect)
|
redirect=redirect)
|
||||||
instances = []
|
instances = []
|
||||||
for server in servers:
|
for target in targets:
|
||||||
server_name = "%s (%s)" % (server.name, server.id)
|
instances.append((target.id, target.name))
|
||||||
instances.append((server.id, server_name))
|
|
||||||
|
|
||||||
# Sort instances for easy browsing
|
# Sort instances for easy browsing
|
||||||
instances = sorted(instances, key=lambda x: x[1])
|
instances = sorted(instances, key=lambda x: x[1])
|
||||||
|
|
||||||
|
quantum_enabled = api.base.is_service_enabled(request, 'network')
|
||||||
if instances:
|
if instances:
|
||||||
instances.insert(0, ("", _("Select an instance")))
|
if quantum_enabled:
|
||||||
|
label = _("Select a port")
|
||||||
else:
|
else:
|
||||||
instances = (("", _("No instances available")),)
|
label = _("Select an instance")
|
||||||
|
instances.insert(0, ("", label))
|
||||||
|
else:
|
||||||
|
if quantum_enabled:
|
||||||
|
label = _("No ports available")
|
||||||
|
else:
|
||||||
|
label = _("No instances available")
|
||||||
|
instances = (("", label),)
|
||||||
return instances
|
return instances
|
||||||
|
|
||||||
|
|
||||||
@ -108,9 +135,9 @@ class IPAssociationWorkflow(workflows.Workflow):
|
|||||||
|
|
||||||
def handle(self, request, data):
|
def handle(self, request, data):
|
||||||
try:
|
try:
|
||||||
api.nova.server_add_floating_ip(request,
|
api.network.floating_ip_associate(request,
|
||||||
data['instance_id'],
|
data['ip_id'],
|
||||||
data['ip_id'])
|
data['instance_id'])
|
||||||
except:
|
except:
|
||||||
exceptions.handle(request)
|
exceptions.handle(request)
|
||||||
return False
|
return False
|
||||||
|
@ -37,14 +37,14 @@ class KeyPairViewTests(test.TestCase):
|
|||||||
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
||||||
self.mox.StubOutWithMock(api.nova, 'keypair_delete')
|
self.mox.StubOutWithMock(api.nova, 'keypair_delete')
|
||||||
self.mox.StubOutWithMock(api.nova, 'security_group_list')
|
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')
|
self.mox.StubOutWithMock(api.nova, 'server_list')
|
||||||
|
|
||||||
api.nova.server_list(IsA(http.HttpRequest),
|
api.nova.server_list(IsA(http.HttpRequest),
|
||||||
all_tenants=True).AndReturn(self.servers.list())
|
all_tenants=True).AndReturn(self.servers.list())
|
||||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||||
.AndReturn(self.security_groups.list())
|
.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())
|
.AndReturn(self.floating_ips.list())
|
||||||
api.nova.keypair_list(IsA(http.HttpRequest)) \
|
api.nova.keypair_list(IsA(http.HttpRequest)) \
|
||||||
.AndReturn(self.keypairs.list())
|
.AndReturn(self.keypairs.list())
|
||||||
@ -60,14 +60,14 @@ class KeyPairViewTests(test.TestCase):
|
|||||||
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
||||||
self.mox.StubOutWithMock(api.nova, 'keypair_delete')
|
self.mox.StubOutWithMock(api.nova, 'keypair_delete')
|
||||||
self.mox.StubOutWithMock(api.nova, 'security_group_list')
|
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')
|
self.mox.StubOutWithMock(api.nova, 'server_list')
|
||||||
|
|
||||||
api.nova.server_list(IsA(http.HttpRequest),
|
api.nova.server_list(IsA(http.HttpRequest),
|
||||||
all_tenants=True).AndReturn(self.servers.list())
|
all_tenants=True).AndReturn(self.servers.list())
|
||||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||||
.AndReturn(self.security_groups.list())
|
.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())
|
.AndReturn(self.floating_ips.list())
|
||||||
api.nova.keypair_list(IsA(http.HttpRequest)) \
|
api.nova.keypair_list(IsA(http.HttpRequest)) \
|
||||||
.AndReturn(self.keypairs.list())
|
.AndReturn(self.keypairs.list())
|
||||||
|
@ -30,11 +30,14 @@ from openstack_dashboard.test import helpers as test
|
|||||||
|
|
||||||
|
|
||||||
class AccessAndSecurityTests(test.TestCase):
|
class AccessAndSecurityTests(test.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(AccessAndSecurityTests, self).setUp()
|
||||||
|
|
||||||
def test_index(self):
|
def test_index(self):
|
||||||
keypairs = self.keypairs.list()
|
keypairs = self.keypairs.list()
|
||||||
sec_groups = self.security_groups.list()
|
sec_groups = self.security_groups.list()
|
||||||
floating_ips = self.floating_ips.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, 'security_group_list')
|
||||||
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
self.mox.StubOutWithMock(api.nova, 'keypair_list')
|
||||||
self.mox.StubOutWithMock(api.nova, 'server_list')
|
self.mox.StubOutWithMock(api.nova, 'server_list')
|
||||||
@ -42,7 +45,7 @@ class AccessAndSecurityTests(test.TestCase):
|
|||||||
api.nova.server_list(IsA(http.HttpRequest),
|
api.nova.server_list(IsA(http.HttpRequest),
|
||||||
all_tenants=True).AndReturn(self.servers.list())
|
all_tenants=True).AndReturn(self.servers.list())
|
||||||
api.nova.keypair_list(IsA(http.HttpRequest)).AndReturn(keypairs)
|
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)
|
.AndReturn(floating_ips)
|
||||||
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
api.nova.security_group_list(IsA(http.HttpRequest)) \
|
||||||
.AndReturn(sec_groups)
|
.AndReturn(sec_groups)
|
||||||
@ -60,21 +63,24 @@ class AccessAndSecurityTests(test.TestCase):
|
|||||||
floating_ips)
|
floating_ips)
|
||||||
|
|
||||||
def test_association(self):
|
def test_association(self):
|
||||||
servers = self.servers.list()
|
servers = [api.nova.Server(s, self.request)
|
||||||
|
for s in self.servers.list()]
|
||||||
# Add duplicate instance name to test instance name with [IP]
|
# Add duplicate instance name to test instance name with [ID]
|
||||||
# change id and private IP
|
# Change id and private IP
|
||||||
server3 = api.nova.Server(self.servers.first(), self.request)
|
server3 = api.nova.Server(self.servers.first(), self.request)
|
||||||
server3.id = 101
|
server3.id = 101
|
||||||
server3.addresses = deepcopy(server3.addresses)
|
server3.addresses = deepcopy(server3.addresses)
|
||||||
server3.addresses['private'][0]['addr'] = "10.0.0.5"
|
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')
|
targets = [api.nova.FloatingIpTarget(s) for s in servers]
|
||||||
self.mox.StubOutWithMock(api.nova, 'server_list')
|
|
||||||
api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
|
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())
|
.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()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
res = self.client.get(reverse("horizon:project:access_and_security:"
|
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>')
|
self.assertContains(res, '<option value="2">server_2 (2)</option>')
|
||||||
|
|
||||||
|
|
||||||
class AccessAndSecurityQuantumTests(AccessAndSecurityTests):
|
class AccessAndSecurityQuantumProxyTests(AccessAndSecurityTests):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(AccessAndSecurityTests, self).setUp()
|
super(AccessAndSecurityQuantumProxyTests, self).setUp()
|
||||||
self.floating_ips = self.floating_ips_uuid
|
self.floating_ips = self.floating_ips_uuid
|
||||||
|
@ -27,9 +27,11 @@ import logging
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from horizon import exceptions
|
from horizon import exceptions
|
||||||
|
from horizon import messages
|
||||||
from horizon import tables
|
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 .keypairs.tables import KeypairsTable
|
||||||
from .floating_ips.tables import FloatingIPsTable
|
from .floating_ips.tables import FloatingIPsTable
|
||||||
from .security_groups.tables import SecurityGroupsTable
|
from .security_groups.tables import SecurityGroupsTable
|
||||||
@ -44,7 +46,7 @@ class IndexView(tables.MultiTableView):
|
|||||||
|
|
||||||
def get_keypairs_data(self):
|
def get_keypairs_data(self):
|
||||||
try:
|
try:
|
||||||
keypairs = api.nova.keypair_list(self.request)
|
keypairs = nova.keypair_list(self.request)
|
||||||
except:
|
except:
|
||||||
keypairs = []
|
keypairs = []
|
||||||
exceptions.handle(self.request,
|
exceptions.handle(self.request,
|
||||||
@ -53,7 +55,7 @@ class IndexView(tables.MultiTableView):
|
|||||||
|
|
||||||
def get_security_groups_data(self):
|
def get_security_groups_data(self):
|
||||||
try:
|
try:
|
||||||
security_groups = api.nova.security_group_list(self.request)
|
security_groups = nova.security_group_list(self.request)
|
||||||
except:
|
except:
|
||||||
security_groups = []
|
security_groups = []
|
||||||
exceptions.handle(self.request,
|
exceptions.handle(self.request,
|
||||||
@ -62,15 +64,23 @@ class IndexView(tables.MultiTableView):
|
|||||||
|
|
||||||
def get_floating_ips_data(self):
|
def get_floating_ips_data(self):
|
||||||
try:
|
try:
|
||||||
floating_ips = api.nova.tenant_floating_ip_list(self.request)
|
floating_ips = network.tenant_floating_ip_list(self.request)
|
||||||
except:
|
except:
|
||||||
floating_ips = []
|
floating_ips = []
|
||||||
exceptions.handle(self.request,
|
exceptions.handle(self.request,
|
||||||
_('Unable to retrieve floating IP addresses.'))
|
_('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 = []
|
instances = []
|
||||||
try:
|
try:
|
||||||
instances = api.nova.server_list(self.request, all_tenants=True)
|
instances = nova.server_list(self.request, all_tenants=True)
|
||||||
except:
|
except:
|
||||||
exceptions.handle(self.request,
|
exceptions.handle(self.request,
|
||||||
_('Unable to retrieve instance list.'))
|
_('Unable to retrieve instance list.'))
|
||||||
@ -80,5 +90,6 @@ class IndexView(tables.MultiTableView):
|
|||||||
for ip in floating_ips:
|
for ip in floating_ips:
|
||||||
ip.instance_name = instances_dict[ip.instance_id].name \
|
ip.instance_name = instances_dict[ip.instance_id].name \
|
||||||
if ip.instance_id in instances_dict else None
|
if ip.instance_id in instances_dict else None
|
||||||
|
ip.pool_name = pool_dict.get(ip.pool, ip.pool)
|
||||||
|
|
||||||
return floating_ips
|
return floating_ips
|
||||||
|
@ -276,7 +276,8 @@ class AssociateIP(tables.LinkAction):
|
|||||||
classes = ("ajax-modal", "btn-associate")
|
classes = ("ajax-modal", "btn-associate")
|
||||||
|
|
||||||
def allowed(self, request, instance):
|
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 False
|
||||||
return not is_deleting(instance)
|
return not is_deleting(instance)
|
||||||
|
|
||||||
@ -290,19 +291,20 @@ class AssociateIP(tables.LinkAction):
|
|||||||
|
|
||||||
|
|
||||||
class SimpleAssociateIP(tables.Action):
|
class SimpleAssociateIP(tables.Action):
|
||||||
name = "associate"
|
name = "associate-simple"
|
||||||
verbose_name = _("Associate Floating IP")
|
verbose_name = _("Associate Floating IP")
|
||||||
classes = ("btn-associate",)
|
classes = ("btn-associate-simple",)
|
||||||
|
|
||||||
def allowed(self, request, instance):
|
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 False
|
||||||
return not is_deleting(instance)
|
return not is_deleting(instance)
|
||||||
|
|
||||||
def single(self, table, request, instance):
|
def single(self, table, request, instance):
|
||||||
try:
|
try:
|
||||||
fip = api.nova.tenant_floating_ip_allocate(request)
|
fip = api.network.tenant_floating_ip_allocate(request)
|
||||||
api.nova.server_add_floating_ip(request, instance, fip.id)
|
api.network.floating_ip_associate(request, fip.id, instance)
|
||||||
messages.success(request,
|
messages.success(request,
|
||||||
_("Successfully associated floating IP: %s")
|
_("Successfully associated floating IP: %s")
|
||||||
% fip.ip)
|
% fip.ip)
|
||||||
@ -312,12 +314,6 @@ class SimpleAssociateIP(tables.Action):
|
|||||||
return shortcuts.redirect("horizon:project:instances:index")
|
return shortcuts.redirect("horizon:project:instances:index")
|
||||||
|
|
||||||
|
|
||||||
if HORIZON_CONFIG["simple_ip_management"]:
|
|
||||||
CurrentAssociateIP = SimpleAssociateIP
|
|
||||||
else:
|
|
||||||
CurrentAssociateIP = AssociateIP
|
|
||||||
|
|
||||||
|
|
||||||
class SimpleDisassociateIP(tables.Action):
|
class SimpleDisassociateIP(tables.Action):
|
||||||
name = "disassociate"
|
name = "disassociate"
|
||||||
verbose_name = _("Disassociate Floating IP")
|
verbose_name = _("Disassociate Floating IP")
|
||||||
@ -330,16 +326,15 @@ class SimpleDisassociateIP(tables.Action):
|
|||||||
|
|
||||||
def single(self, table, request, instance_id):
|
def single(self, table, request, instance_id):
|
||||||
try:
|
try:
|
||||||
fips = [fip for fip in api.nova.tenant_floating_ip_list(request)
|
fips = [fip for fip in api.network.tenant_floating_ip_list(request)
|
||||||
if fip.instance_id == instance_id]
|
if fip.port_id == instance_id]
|
||||||
# Removing multiple floating IPs at once doesn't work, so this pops
|
# Removing multiple floating IPs at once doesn't work, so this pops
|
||||||
# off the first one.
|
# off the first one.
|
||||||
if fips:
|
if fips:
|
||||||
fip = fips.pop()
|
fip = fips.pop()
|
||||||
api.nova.server_remove_floating_ip(request,
|
api.network.floating_ip_disassociate(request,
|
||||||
instance_id,
|
fip.id, instance_id)
|
||||||
fip.id)
|
api.network.tenant_floating_ip_release(request, fip.id)
|
||||||
api.nova.tenant_floating_ip_release(request, fip.id)
|
|
||||||
messages.success(request,
|
messages.success(request,
|
||||||
_("Successfully disassociated "
|
_("Successfully disassociated "
|
||||||
"floating IP: %s") % fip.ip)
|
"floating IP: %s") % fip.ip)
|
||||||
@ -452,6 +447,7 @@ class InstancesTable(tables.DataTable):
|
|||||||
row_class = UpdateRow
|
row_class = UpdateRow
|
||||||
table_actions = (LaunchLink, TerminateInstance)
|
table_actions = (LaunchLink, TerminateInstance)
|
||||||
row_actions = (ConfirmResize, RevertResize, CreateSnapshot,
|
row_actions = (ConfirmResize, RevertResize, CreateSnapshot,
|
||||||
CurrentAssociateIP, SimpleDisassociateIP, EditInstance,
|
SimpleAssociateIP, AssociateIP,
|
||||||
|
SimpleDisassociateIP, EditInstance,
|
||||||
ConsoleLink, LogLink, TogglePause, ToggleSuspend,
|
ConsoleLink, LogLink, TogglePause, ToggleSuspend,
|
||||||
RebootInstance, TerminateInstance)
|
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)
|
ret_val = api.nova.server_get(self.request, server.id)
|
||||||
self.assertIsInstance(ret_val, api.nova.Server)
|
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):
|
def test_absolute_limits_handle_unlimited(self):
|
||||||
values = {"maxTotalCores": -1, "maxTotalInstances": 10}
|
values = {"maxTotalCores": -1, "maxTotalInstances": 10}
|
||||||
limits = self.mox.CreateMockAnything()
|
limits = self.mox.CreateMockAnything()
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import copy
|
||||||
import json
|
import json
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
@ -23,6 +24,7 @@ from novaclient.v1_1 import (flavors, keypairs, servers, volumes,
|
|||||||
security_groups as sec_groups)
|
security_groups as sec_groups)
|
||||||
|
|
||||||
from openstack_dashboard.api.base import Quota, QuotaSet as QuotaSetWrapper
|
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 openstack_dashboard.usage.quotas import QuotaUsage
|
||||||
from .utils import TestDataContainer
|
from .utils import TestDataContainer
|
||||||
|
|
||||||
@ -150,6 +152,11 @@ def data(TEST):
|
|||||||
TEST.volume_snapshots = TestDataContainer()
|
TEST.volume_snapshots = TestDataContainer()
|
||||||
TEST.volume_types = 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
|
# Volumes
|
||||||
volume = volumes.Volume(volumes.VolumeManager(None),
|
volume = volumes.Volume(volumes.VolumeManager(None),
|
||||||
dict(id="41023e92-8008-4c8b-8059-7f2293ff3775",
|
dict(id="41023e92-8008-4c8b-8059-7f2293ff3775",
|
||||||
@ -356,26 +363,36 @@ def data(TEST):
|
|||||||
{'id': 1,
|
{'id': 1,
|
||||||
'fixed_ip': '10.0.0.4',
|
'fixed_ip': '10.0.0.4',
|
||||||
'instance_id': server_1.id,
|
'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),
|
fip_2 = floating_ips.FloatingIP(floating_ips.FloatingIPManager(None),
|
||||||
{'id': 2,
|
{'id': 2,
|
||||||
'fixed_ip': None,
|
'fixed_ip': None,
|
||||||
'instance_id': None,
|
'instance_id': None,
|
||||||
'ip': '58.58.58.58'})
|
'ip': '58.58.58.58',
|
||||||
TEST.floating_ips.add(fip_1, fip_2)
|
'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),
|
fip_3 = floating_ips.FloatingIP(floating_ips.FloatingIPManager(None),
|
||||||
{'id': str(uuid.uuid4()),
|
{'id': str(uuid.uuid4()),
|
||||||
'fixed_ip': '10.0.0.4',
|
'fixed_ip': '10.0.0.4',
|
||||||
'instance_id': server_1.id,
|
'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),
|
fip_4 = floating_ips.FloatingIP(floating_ips.FloatingIPManager(None),
|
||||||
{'id': str(uuid.uuid4()),
|
{'id': str(uuid.uuid4()),
|
||||||
'fixed_ip': None,
|
'fixed_ip': None,
|
||||||
'instance_id': None,
|
'instance_id': None,
|
||||||
'ip': '58.58.58.58'})
|
'ip': '58.58.58.58',
|
||||||
TEST.floating_ips_uuid.add(fip_3, fip_4)
|
'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
|
||||||
usage_vals = {"tenant_id": TEST.tenant.id,
|
usage_vals = {"tenant_id": TEST.tenant.id,
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
|
|
||||||
import copy
|
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
|
from .utils import TestDataContainer
|
||||||
|
|
||||||
@ -25,13 +26,16 @@ def data(TEST):
|
|||||||
TEST.subnets = TestDataContainer()
|
TEST.subnets = TestDataContainer()
|
||||||
TEST.ports = TestDataContainer()
|
TEST.ports = TestDataContainer()
|
||||||
TEST.routers = TestDataContainer()
|
TEST.routers = TestDataContainer()
|
||||||
|
TEST.q_floating_ips = TestDataContainer()
|
||||||
|
|
||||||
# data return by quantumclient
|
# data return by quantumclient
|
||||||
TEST.api_networks = TestDataContainer()
|
TEST.api_networks = TestDataContainer()
|
||||||
TEST.api_subnets = TestDataContainer()
|
TEST.api_subnets = TestDataContainer()
|
||||||
TEST.api_ports = TestDataContainer()
|
TEST.api_ports = TestDataContainer()
|
||||||
TEST.api_routers = TestDataContainer()
|
TEST.api_routers = TestDataContainer()
|
||||||
|
TEST.api_q_floating_ips = TestDataContainer()
|
||||||
|
|
||||||
|
#------------------------------------------------------------
|
||||||
# 1st network
|
# 1st network
|
||||||
network_dict = {'admin_state_up': True,
|
network_dict = {'admin_state_up': True,
|
||||||
'id': '82288d84-e0a5-42ac-95be-e6af08727e42',
|
'id': '82288d84-e0a5-42ac-95be-e6af08727e42',
|
||||||
@ -53,6 +57,17 @@ def data(TEST):
|
|||||||
'name': 'mysubnet1',
|
'name': 'mysubnet1',
|
||||||
'network_id': network_dict['id'],
|
'network_id': network_dict['id'],
|
||||||
'tenant_id': network_dict['tenant_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,
|
port_dict = {'admin_state_up': True,
|
||||||
'device_id': 'af75c8e5-a1cc-4567-8d04-44fcd6922890',
|
'device_id': 'af75c8e5-a1cc-4567-8d04-44fcd6922890',
|
||||||
'device_owner': 'network:dhcp',
|
'device_owner': 'network:dhcp',
|
||||||
@ -64,17 +79,25 @@ def data(TEST):
|
|||||||
'network_id': network_dict['id'],
|
'network_id': network_dict['id'],
|
||||||
'status': 'ACTIVE',
|
'status': 'ACTIVE',
|
||||||
'tenant_id': network_dict['tenant_id']}
|
'tenant_id': network_dict['tenant_id']}
|
||||||
TEST.api_networks.add(network_dict)
|
|
||||||
TEST.api_subnets.add(subnet_dict)
|
|
||||||
TEST.api_ports.add(port_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))
|
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
|
# 2nd network
|
||||||
network_dict = {'admin_state_up': True,
|
network_dict = {'admin_state_up': True,
|
||||||
'id': '72c3ab6c-c80f-4341-9dc5-210fa31ac6c2',
|
'id': '72c3ab6c-c80f-4341-9dc5-210fa31ac6c2',
|
||||||
@ -82,7 +105,7 @@ def data(TEST):
|
|||||||
'status': 'ACTIVE',
|
'status': 'ACTIVE',
|
||||||
'subnets': ['3f7c5d79-ee55-47b0-9213-8e669fb03009'],
|
'subnets': ['3f7c5d79-ee55-47b0-9213-8e669fb03009'],
|
||||||
'tenant_id': '2',
|
'tenant_id': '2',
|
||||||
'router:external': True,
|
'router:external': False,
|
||||||
'shared': True}
|
'shared': True}
|
||||||
subnet_dict = {'allocation_pools': [{'end': '172.16.88.254',
|
subnet_dict = {'allocation_pools': [{'end': '172.16.88.254',
|
||||||
'start': '172.16.88.2'}],
|
'start': '172.16.88.2'}],
|
||||||
@ -99,28 +122,66 @@ def data(TEST):
|
|||||||
'name': 'aaaa',
|
'name': 'aaaa',
|
||||||
'network_id': network_dict['id'],
|
'network_id': network_dict['id'],
|
||||||
'tenant_id': network_dict['tenant_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_networks.add(network_dict)
|
||||||
TEST.api_subnets.add(subnet_dict)
|
TEST.api_subnets.add(subnet_dict)
|
||||||
TEST.api_ports.add(port_dict)
|
|
||||||
|
|
||||||
network = copy.deepcopy(network_dict)
|
network = copy.deepcopy(network_dict)
|
||||||
subnet = Subnet(subnet_dict)
|
subnet = Subnet(subnet_dict)
|
||||||
network['subnets'] = [subnet]
|
network['subnets'] = [subnet]
|
||||||
TEST.networks.add(Network(network))
|
TEST.networks.add(Network(network))
|
||||||
TEST.subnets.add(subnet)
|
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))
|
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
|
# Set up router data
|
||||||
port_dict = {'admin_state_up': True,
|
port_dict = {'admin_state_up': True,
|
||||||
'device_id': '7180cede-bcd8-4334-b19f-f7ef2f331f53',
|
'device_id': '7180cede-bcd8-4334-b19f-f7ef2f331f53',
|
||||||
@ -146,3 +207,27 @@ def data(TEST):
|
|||||||
'tenant_id': '1'}
|
'tenant_id': '1'}
|
||||||
TEST.api_routers.add(router_dict)
|
TEST.api_routers.add(router_dict)
|
||||||
TEST.routers.add(Router(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):
|
class QuotaTests(test.APITestCase):
|
||||||
@test.create_stubs({api.nova: ('server_list',
|
@test.create_stubs({api.nova: ('server_list',
|
||||||
'flavor_list',
|
'flavor_list',
|
||||||
'tenant_floating_ip_list',
|
|
||||||
'tenant_quota_get',),
|
'tenant_quota_get',),
|
||||||
|
api.network: ('tenant_floating_ip_list',),
|
||||||
quotas: ('is_service_enabled',),
|
quotas: ('is_service_enabled',),
|
||||||
cinder: ('volume_list', 'tenant_quota_get',)})
|
cinder: ('volume_list', 'tenant_quota_get',)})
|
||||||
def test_tenant_quota_usages(self):
|
def test_tenant_quota_usages(self):
|
||||||
@ -44,7 +44,7 @@ class QuotaTests(test.APITestCase):
|
|||||||
.AndReturn(self.flavors.list())
|
.AndReturn(self.flavors.list())
|
||||||
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||||
.AndReturn(self.quotas.first())
|
.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())
|
.AndReturn(self.floating_ips.list())
|
||||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||||
.AndReturn(self.servers.list())
|
.AndReturn(self.servers.list())
|
||||||
@ -73,8 +73,8 @@ class QuotaTests(test.APITestCase):
|
|||||||
|
|
||||||
@test.create_stubs({api.nova: ('server_list',
|
@test.create_stubs({api.nova: ('server_list',
|
||||||
'flavor_list',
|
'flavor_list',
|
||||||
'tenant_floating_ip_list',
|
|
||||||
'tenant_quota_get',),
|
'tenant_quota_get',),
|
||||||
|
api.network: ('tenant_floating_ip_list',),
|
||||||
quotas: ('is_service_enabled',)})
|
quotas: ('is_service_enabled',)})
|
||||||
def test_tenant_quota_usages_without_volume(self):
|
def test_tenant_quota_usages_without_volume(self):
|
||||||
quotas.is_service_enabled(IsA(http.HttpRequest),
|
quotas.is_service_enabled(IsA(http.HttpRequest),
|
||||||
@ -83,7 +83,7 @@ class QuotaTests(test.APITestCase):
|
|||||||
.AndReturn(self.flavors.list())
|
.AndReturn(self.flavors.list())
|
||||||
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||||
.AndReturn(self.quotas.first())
|
.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())
|
.AndReturn(self.floating_ips.list())
|
||||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||||
.AndReturn(self.servers.list())
|
.AndReturn(self.servers.list())
|
||||||
@ -106,8 +106,8 @@ class QuotaTests(test.APITestCase):
|
|||||||
|
|
||||||
@test.create_stubs({api.nova: ('server_list',
|
@test.create_stubs({api.nova: ('server_list',
|
||||||
'flavor_list',
|
'flavor_list',
|
||||||
'tenant_floating_ip_list',
|
|
||||||
'tenant_quota_get',),
|
'tenant_quota_get',),
|
||||||
|
api.network: ('tenant_floating_ip_list',),
|
||||||
quotas: ('is_service_enabled',)})
|
quotas: ('is_service_enabled',)})
|
||||||
def test_tenant_quota_usages_no_instances_running(self):
|
def test_tenant_quota_usages_no_instances_running(self):
|
||||||
quotas.is_service_enabled(IsA(http.HttpRequest),
|
quotas.is_service_enabled(IsA(http.HttpRequest),
|
||||||
@ -116,7 +116,8 @@ class QuotaTests(test.APITestCase):
|
|||||||
.AndReturn(self.flavors.list())
|
.AndReturn(self.flavors.list())
|
||||||
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||||
.AndReturn(self.quotas.first())
|
.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([])
|
api.nova.server_list(IsA(http.HttpRequest)).AndReturn([])
|
||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
@ -137,8 +138,8 @@ class QuotaTests(test.APITestCase):
|
|||||||
|
|
||||||
@test.create_stubs({api.nova: ('server_list',
|
@test.create_stubs({api.nova: ('server_list',
|
||||||
'flavor_list',
|
'flavor_list',
|
||||||
'tenant_floating_ip_list',
|
|
||||||
'tenant_quota_get',),
|
'tenant_quota_get',),
|
||||||
|
api.network: ('tenant_floating_ip_list',),
|
||||||
quotas: ('is_service_enabled',),
|
quotas: ('is_service_enabled',),
|
||||||
cinder: ('volume_list', 'tenant_quota_get',)})
|
cinder: ('volume_list', 'tenant_quota_get',)})
|
||||||
def test_tenant_quota_usages_unlimited_quota(self):
|
def test_tenant_quota_usages_unlimited_quota(self):
|
||||||
@ -151,7 +152,7 @@ class QuotaTests(test.APITestCase):
|
|||||||
.AndReturn(self.flavors.list())
|
.AndReturn(self.flavors.list())
|
||||||
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
|
||||||
.AndReturn(inf_quota)
|
.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())
|
.AndReturn(self.floating_ips.list())
|
||||||
api.nova.server_list(IsA(http.HttpRequest)) \
|
api.nova.server_list(IsA(http.HttpRequest)) \
|
||||||
.AndReturn(self.servers.list())
|
.AndReturn(self.servers.list())
|
||||||
|
@ -4,7 +4,7 @@ import itertools
|
|||||||
from horizon import exceptions
|
from horizon import exceptions
|
||||||
from horizon.utils.memoized import memoized
|
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
|
from openstack_dashboard.api.base import is_service_enabled, QuotaSet
|
||||||
|
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ def tenant_quota_usages(request):
|
|||||||
usages.add_quota(quota)
|
usages.add_quota(quota)
|
||||||
|
|
||||||
# Get our usages.
|
# 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)])
|
flavors = dict([(f.id, f) for f in nova.flavor_list(request)])
|
||||||
instances = nova.server_list(request)
|
instances = nova.server_list(request)
|
||||||
# Fetch deleted flavors if necessary.
|
# Fetch deleted flavors if necessary.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user