Add Quantum public network support.
Implements blueprint quantum-public-network. Change-Id: I975532468b95c9198091ebf85c475d341d7e861a
This commit is contained in:
parent
b177299953
commit
7d2e14cf84
@ -50,7 +50,8 @@ class QuantumAPIDictWrapper(APIDictWrapper):
|
|||||||
|
|
||||||
class Network(QuantumAPIDictWrapper):
|
class Network(QuantumAPIDictWrapper):
|
||||||
"""Wrapper for quantum Networks"""
|
"""Wrapper for quantum Networks"""
|
||||||
_attrs = ['name', 'id', 'subnets', 'tenant_id', 'status', 'admin_state_up']
|
_attrs = ['name', 'id', 'subnets', 'tenant_id', 'status',
|
||||||
|
'admin_state_up', 'shared']
|
||||||
|
|
||||||
def __init__(self, apiresource):
|
def __init__(self, apiresource):
|
||||||
apiresource['admin_state'] = \
|
apiresource['admin_state'] = \
|
||||||
@ -110,6 +111,27 @@ def network_list(request, **params):
|
|||||||
return [Network(n) for n in networks]
|
return [Network(n) for n in networks]
|
||||||
|
|
||||||
|
|
||||||
|
def network_list_for_tenant(request, tenant_id, **params):
|
||||||
|
"""Return a network list available for the tenant.
|
||||||
|
The list contains networks owned by the tenant and public networks.
|
||||||
|
If requested_networks specified, it searches requested_networks only.
|
||||||
|
"""
|
||||||
|
LOG.debug("network_list_for_tenant(): tenant_id=%s, params=%s"
|
||||||
|
% (tenant_id, params))
|
||||||
|
|
||||||
|
# If a user has admin role, network list returned by Quantum API
|
||||||
|
# contains networks that do not belong to that tenant.
|
||||||
|
# So we need to specify tenant_id when calling network_list().
|
||||||
|
networks = network_list(request, tenant_id=tenant_id,
|
||||||
|
shared=False, **params)
|
||||||
|
|
||||||
|
# In the current Quantum API, there is no way to retrieve
|
||||||
|
# both owner networks and public networks in a single API call.
|
||||||
|
networks += network_list(request, shared=True, **params)
|
||||||
|
|
||||||
|
return networks
|
||||||
|
|
||||||
|
|
||||||
def network_get(request, network_id, **params):
|
def network_get(request, network_id, **params):
|
||||||
LOG.debug("network_get(): netid=%s, params=%s" % (network_id, params))
|
LOG.debug("network_get(): netid=%s, params=%s" % (network_id, params))
|
||||||
network = quantumclient(request).show_network(network_id,
|
network = quantumclient(request).show_network(network_id,
|
||||||
|
@ -608,8 +608,12 @@ class InstanceTests(test.TestCase):
|
|||||||
'status': 'active'}) \
|
'status': 'active'}) \
|
||||||
.AndReturn([[], False])
|
.AndReturn([[], False])
|
||||||
api.quantum.network_list(IsA(http.HttpRequest),
|
api.quantum.network_list(IsA(http.HttpRequest),
|
||||||
tenant_id=self.tenant.id) \
|
tenant_id=self.tenant.id,
|
||||||
.AndReturn(self.networks.list())
|
shared=False) \
|
||||||
|
.AndReturn(self.networks.list()[:1])
|
||||||
|
api.quantum.network_list(IsA(http.HttpRequest),
|
||||||
|
shared=True) \
|
||||||
|
.AndReturn(self.networks.list()[1:])
|
||||||
api.nova.tenant_quota_usages(IsA(http.HttpRequest)) \
|
api.nova.tenant_quota_usages(IsA(http.HttpRequest)) \
|
||||||
.AndReturn(quota_usages)
|
.AndReturn(quota_usages)
|
||||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||||
@ -678,8 +682,12 @@ class InstanceTests(test.TestCase):
|
|||||||
'status': 'active'}) \
|
'status': 'active'}) \
|
||||||
.AndReturn([[], False])
|
.AndReturn([[], False])
|
||||||
api.quantum.network_list(IsA(http.HttpRequest),
|
api.quantum.network_list(IsA(http.HttpRequest),
|
||||||
tenant_id=self.tenant.id) \
|
tenant_id=self.tenant.id,
|
||||||
.AndReturn(self.networks.list())
|
shared=False) \
|
||||||
|
.AndReturn(self.networks.list()[:1])
|
||||||
|
api.quantum.network_list(IsA(http.HttpRequest),
|
||||||
|
shared=True) \
|
||||||
|
.AndReturn(self.networks.list()[1:])
|
||||||
api.nova.volume_list(IsA(http.HttpRequest)) \
|
api.nova.volume_list(IsA(http.HttpRequest)) \
|
||||||
.AndReturn(self.volumes.list())
|
.AndReturn(self.volumes.list())
|
||||||
api.nova.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])
|
api.nova.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])
|
||||||
@ -747,8 +755,12 @@ class InstanceTests(test.TestCase):
|
|||||||
'status': 'active'}) \
|
'status': 'active'}) \
|
||||||
.AndReturn([[], False])
|
.AndReturn([[], False])
|
||||||
api.quantum.network_list(IsA(http.HttpRequest),
|
api.quantum.network_list(IsA(http.HttpRequest),
|
||||||
tenant_id=self.tenant.id) \
|
tenant_id=self.tenant.id,
|
||||||
.AndReturn(self.networks.list())
|
shared=False) \
|
||||||
|
.AndReturn(self.networks.list()[:1])
|
||||||
|
api.quantum.network_list(IsA(http.HttpRequest),
|
||||||
|
shared=True) \
|
||||||
|
.AndReturn(self.networks.list()[1:])
|
||||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||||
.AndReturn(self.flavors.list())
|
.AndReturn(self.flavors.list())
|
||||||
api.nova.keypair_list(IsA(http.HttpRequest)) \
|
api.nova.keypair_list(IsA(http.HttpRequest)) \
|
||||||
@ -805,8 +817,12 @@ class InstanceTests(test.TestCase):
|
|||||||
'status': 'active'}) \
|
'status': 'active'}) \
|
||||||
.AndReturn([[], False])
|
.AndReturn([[], False])
|
||||||
api.quantum.network_list(IsA(http.HttpRequest),
|
api.quantum.network_list(IsA(http.HttpRequest),
|
||||||
tenant_id=self.tenant.id) \
|
tenant_id=self.tenant.id,
|
||||||
.AndReturn(self.networks.list())
|
shared=False) \
|
||||||
|
.AndReturn(self.networks.list()[:1])
|
||||||
|
api.quantum.network_list(IsA(http.HttpRequest),
|
||||||
|
shared=True) \
|
||||||
|
.AndReturn(self.networks.list()[1:])
|
||||||
api.nova.tenant_quota_usages(IsA(http.HttpRequest)) \
|
api.nova.tenant_quota_usages(IsA(http.HttpRequest)) \
|
||||||
.AndReturn(self.quota_usages.first())
|
.AndReturn(self.quota_usages.first())
|
||||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||||
@ -858,8 +874,12 @@ class InstanceTests(test.TestCase):
|
|||||||
'status': 'active'}) \
|
'status': 'active'}) \
|
||||||
.AndReturn([[], False])
|
.AndReturn([[], False])
|
||||||
api.quantum.network_list(IsA(http.HttpRequest),
|
api.quantum.network_list(IsA(http.HttpRequest),
|
||||||
tenant_id=self.tenant.id) \
|
tenant_id=self.tenant.id,
|
||||||
.AndReturn(self.networks.list())
|
shared=False) \
|
||||||
|
.AndReturn(self.networks.list()[:1])
|
||||||
|
api.quantum.network_list(IsA(http.HttpRequest),
|
||||||
|
shared=True) \
|
||||||
|
.AndReturn(self.networks.list()[1:])
|
||||||
api.nova.volume_list(IgnoreArg()).AndReturn(self.volumes.list())
|
api.nova.volume_list(IgnoreArg()).AndReturn(self.volumes.list())
|
||||||
api.nova.server_create(IsA(http.HttpRequest),
|
api.nova.server_create(IsA(http.HttpRequest),
|
||||||
server.name,
|
server.name,
|
||||||
@ -926,8 +946,12 @@ class InstanceTests(test.TestCase):
|
|||||||
'status': 'active'}) \
|
'status': 'active'}) \
|
||||||
.AndReturn([[], False])
|
.AndReturn([[], False])
|
||||||
api.quantum.network_list(IsA(http.HttpRequest),
|
api.quantum.network_list(IsA(http.HttpRequest),
|
||||||
tenant_id=self.tenant.id) \
|
tenant_id=self.tenant.id,
|
||||||
.AndReturn(self.networks.list())
|
shared=False) \
|
||||||
|
.AndReturn(self.networks.list()[:1])
|
||||||
|
api.quantum.network_list(IsA(http.HttpRequest),
|
||||||
|
shared=True) \
|
||||||
|
.AndReturn(self.networks.list()[1:])
|
||||||
api.nova.volume_list(IsA(http.HttpRequest)) \
|
api.nova.volume_list(IsA(http.HttpRequest)) \
|
||||||
.AndReturn(self.volumes.list())
|
.AndReturn(self.volumes.list())
|
||||||
api.nova.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])
|
api.nova.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])
|
||||||
|
@ -421,12 +421,8 @@ class SetNetworkAction(workflows.Action):
|
|||||||
|
|
||||||
def populate_network_choices(self, request, context):
|
def populate_network_choices(self, request, context):
|
||||||
try:
|
try:
|
||||||
# If a user has admin role, network list returned by Quantum API
|
|
||||||
# contains networks that does not belong to that tenant.
|
|
||||||
# So we need to specify tenant_id when calling network_list().
|
|
||||||
tenant_id = self.request.user.tenant_id
|
tenant_id = self.request.user.tenant_id
|
||||||
networks = api.quantum.network_list(request,
|
networks = api.quantum.network_list_for_tenant(request, tenant_id)
|
||||||
tenant_id=tenant_id)
|
|
||||||
for n in networks:
|
for n in networks:
|
||||||
n.set_id_as_name_if_empty()
|
n.set_id_as_name_if_empty()
|
||||||
network_list = [(network.id, network.name) for network in networks]
|
network_list = [(network.id, network.name) for network in networks]
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse, reverse_lazy
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from horizon import api
|
from horizon import api
|
||||||
@ -27,7 +27,19 @@ from horizon import tables
|
|||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DeleteSubnet(tables.DeleteAction):
|
class CheckNetworkEditable(object):
|
||||||
|
"""Mixin class to determine the specified network is editable."""
|
||||||
|
|
||||||
|
def allowed(self, request, datum=None):
|
||||||
|
# Only administrator is allowed to create and manage subnets
|
||||||
|
# on shared networks.
|
||||||
|
network = self.table._get_network()
|
||||||
|
if network.shared:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteSubnet(CheckNetworkEditable, tables.DeleteAction):
|
||||||
data_type_singular = _("Subnet")
|
data_type_singular = _("Subnet")
|
||||||
data_type_plural = _("Subnets")
|
data_type_plural = _("Subnets")
|
||||||
|
|
||||||
@ -43,7 +55,7 @@ class DeleteSubnet(tables.DeleteAction):
|
|||||||
exceptions.handle(request, msg, redirect=redirect)
|
exceptions.handle(request, msg, redirect=redirect)
|
||||||
|
|
||||||
|
|
||||||
class CreateSubnet(tables.LinkAction):
|
class CreateSubnet(CheckNetworkEditable, tables.LinkAction):
|
||||||
name = "create"
|
name = "create"
|
||||||
verbose_name = _("Create Subnet")
|
verbose_name = _("Create Subnet")
|
||||||
url = "horizon:nova:networks:addsubnet"
|
url = "horizon:nova:networks:addsubnet"
|
||||||
@ -54,7 +66,7 @@ class CreateSubnet(tables.LinkAction):
|
|||||||
return reverse(self.url, args=(network_id,))
|
return reverse(self.url, args=(network_id,))
|
||||||
|
|
||||||
|
|
||||||
class UpdateSubnet(tables.LinkAction):
|
class UpdateSubnet(CheckNetworkEditable, tables.LinkAction):
|
||||||
name = "update"
|
name = "update"
|
||||||
verbose_name = _("Edit Subnet")
|
verbose_name = _("Edit Subnet")
|
||||||
url = "horizon:nova:networks:editsubnet"
|
url = "horizon:nova:networks:editsubnet"
|
||||||
@ -71,6 +83,20 @@ class SubnetsTable(tables.DataTable):
|
|||||||
cidr = tables.Column("cidr", verbose_name=_("Network Address"))
|
cidr = tables.Column("cidr", verbose_name=_("Network Address"))
|
||||||
ip_version = tables.Column("ipver_str", verbose_name=_("IP Version"))
|
ip_version = tables.Column("ipver_str", verbose_name=_("IP Version"))
|
||||||
gateway_ip = tables.Column("gateway_ip", verbose_name=_("Gateway IP"))
|
gateway_ip = tables.Column("gateway_ip", verbose_name=_("Gateway IP"))
|
||||||
|
failure_url = reverse_lazy('horizon:nova:networks:index')
|
||||||
|
|
||||||
|
def _get_network(self):
|
||||||
|
if not hasattr(self, "_network"):
|
||||||
|
try:
|
||||||
|
network_id = self.kwargs['network_id']
|
||||||
|
network = api.quantum.network_get(self.request, network_id)
|
||||||
|
network.set_id_as_name_if_empty(length=0)
|
||||||
|
except:
|
||||||
|
msg = _('Unable to retrieve details for network "%s".') \
|
||||||
|
% (network_id)
|
||||||
|
exceptions.handle(self.request, msg, redirect=self.failure_url)
|
||||||
|
self._network = network
|
||||||
|
return self._network
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
name = "subnets"
|
name = "subnets"
|
||||||
|
@ -17,6 +17,7 @@ import logging
|
|||||||
|
|
||||||
from django import template
|
from django import template
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
|
from django.template import defaultfilters as filters
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from horizon import api
|
from horizon import api
|
||||||
@ -27,7 +28,17 @@ from horizon import tables
|
|||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DeleteNetwork(tables.DeleteAction):
|
class CheckNetworkEditable(object):
|
||||||
|
"""Mixin class to determine the specified network is editable."""
|
||||||
|
|
||||||
|
def allowed(self, request, datum=None):
|
||||||
|
# Only administrator is allowed to create and manage shared networks.
|
||||||
|
if datum and datum.shared:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteNetwork(CheckNetworkEditable, tables.DeleteAction):
|
||||||
data_type_singular = _("Network")
|
data_type_singular = _("Network")
|
||||||
data_type_plural = _("Networks")
|
data_type_plural = _("Networks")
|
||||||
|
|
||||||
@ -57,14 +68,14 @@ class CreateNetwork(tables.LinkAction):
|
|||||||
classes = ("ajax-modal", "btn-create")
|
classes = ("ajax-modal", "btn-create")
|
||||||
|
|
||||||
|
|
||||||
class EditNetwork(tables.LinkAction):
|
class EditNetwork(CheckNetworkEditable, tables.LinkAction):
|
||||||
name = "update"
|
name = "update"
|
||||||
verbose_name = _("Edit Network")
|
verbose_name = _("Edit Network")
|
||||||
url = "horizon:nova:networks:update"
|
url = "horizon:nova:networks:update"
|
||||||
classes = ("ajax-modal", "btn-edit")
|
classes = ("ajax-modal", "btn-edit")
|
||||||
|
|
||||||
|
|
||||||
class CreateSubnet(tables.LinkAction):
|
class CreateSubnet(CheckNetworkEditable, tables.LinkAction):
|
||||||
name = "subnet"
|
name = "subnet"
|
||||||
verbose_name = _("Add Subnet")
|
verbose_name = _("Add Subnet")
|
||||||
url = "horizon:nova:networks:addsubnet"
|
url = "horizon:nova:networks:addsubnet"
|
||||||
@ -83,6 +94,8 @@ class NetworksTable(tables.DataTable):
|
|||||||
link='horizon:nova:networks:detail')
|
link='horizon:nova:networks:detail')
|
||||||
subnets = tables.Column(get_subnets,
|
subnets = tables.Column(get_subnets,
|
||||||
verbose_name=_("Subnets Associated"),)
|
verbose_name=_("Subnets Associated"),)
|
||||||
|
shared = tables.Column("shared", verbose_name=_("Shared"),
|
||||||
|
filters=(filters.yesno, filters.capfirst))
|
||||||
status = tables.Column("status", verbose_name=_("Status"))
|
status = tables.Column("status", verbose_name=_("Status"))
|
||||||
admin_state = tables.Column("admin_state",
|
admin_state = tables.Column("admin_state",
|
||||||
verbose_name=_("Admin State"))
|
verbose_name=_("Admin State"))
|
||||||
|
@ -14,5 +14,7 @@
|
|||||||
<dd>{{ network.status|default:"Unknown" }}</dd>
|
<dd>{{ network.status|default:"Unknown" }}</dd>
|
||||||
<dt>{% trans "Admin State" %}</dt>
|
<dt>{% trans "Admin State" %}</dt>
|
||||||
<dd>{{ network.admin_state|default:"Unknown" }}</dd>
|
<dd>{{ network.admin_state|default:"Unknown" }}</dd>
|
||||||
|
<dt>{% trans "Shared" %}</dt>
|
||||||
|
<dd>{{ network.shared|yesno|capfirst }}</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,9 +34,13 @@ INDEX_URL = reverse('horizon:nova:networks:index')
|
|||||||
class NetworkTests(test.TestCase):
|
class NetworkTests(test.TestCase):
|
||||||
@test.create_stubs({api.quantum: ('network_list',)})
|
@test.create_stubs({api.quantum: ('network_list',)})
|
||||||
def test_index(self):
|
def test_index(self):
|
||||||
api.quantum.network_list(IsA(http.HttpRequest),
|
api.quantum.network_list(
|
||||||
tenant_id=self.tenant.id) \
|
IsA(http.HttpRequest),
|
||||||
.AndReturn(self.networks.list())
|
tenant_id=self.tenant.id,
|
||||||
|
shared=False).AndReturn(self.networks.list())
|
||||||
|
api.quantum.network_list(
|
||||||
|
IsA(http.HttpRequest),
|
||||||
|
shared=True).AndReturn([])
|
||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
@ -48,10 +52,10 @@ class NetworkTests(test.TestCase):
|
|||||||
|
|
||||||
@test.create_stubs({api.quantum: ('network_list',)})
|
@test.create_stubs({api.quantum: ('network_list',)})
|
||||||
def test_index_network_list_exception(self):
|
def test_index_network_list_exception(self):
|
||||||
api.quantum.network_list(IsA(http.HttpRequest),
|
api.quantum.network_list(
|
||||||
tenant_id=self.tenant.id) \
|
IsA(http.HttpRequest),
|
||||||
.AndRaise(self.exceptions.quantum)
|
tenant_id=self.tenant.id,
|
||||||
|
shared=False).AndRaise(self.exceptions.quantum)
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
res = self.client.get(INDEX_URL)
|
res = self.client.get(INDEX_URL)
|
||||||
@ -71,6 +75,8 @@ class NetworkTests(test.TestCase):
|
|||||||
.AndReturn([self.subnets.first()])
|
.AndReturn([self.subnets.first()])
|
||||||
api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id)\
|
api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id)\
|
||||||
.AndReturn([self.ports.first()])
|
.AndReturn([self.ports.first()])
|
||||||
|
api.quantum.network_get(IsA(http.HttpRequest), network_id)\
|
||||||
|
.AndReturn(self.networks.first())
|
||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
@ -90,11 +96,6 @@ class NetworkTests(test.TestCase):
|
|||||||
network_id = self.networks.first().id
|
network_id = self.networks.first().id
|
||||||
api.quantum.network_get(IsA(http.HttpRequest), network_id)\
|
api.quantum.network_get(IsA(http.HttpRequest), network_id)\
|
||||||
.AndRaise(self.exceptions.quantum)
|
.AndRaise(self.exceptions.quantum)
|
||||||
api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network_id)\
|
|
||||||
.AndReturn([self.subnets.first()])
|
|
||||||
api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id)\
|
|
||||||
.AndReturn([self.ports.first()])
|
|
||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
url = reverse('horizon:nova:networks:detail', args=[network_id])
|
url = reverse('horizon:nova:networks:detail', args=[network_id])
|
||||||
@ -114,6 +115,9 @@ class NetworkTests(test.TestCase):
|
|||||||
AndRaise(self.exceptions.quantum)
|
AndRaise(self.exceptions.quantum)
|
||||||
api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id).\
|
api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id).\
|
||||||
AndReturn([self.ports.first()])
|
AndReturn([self.ports.first()])
|
||||||
|
# Called from SubnetTable
|
||||||
|
api.quantum.network_get(IsA(http.HttpRequest), network_id).\
|
||||||
|
AndReturn(self.networks.first())
|
||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
@ -137,6 +141,9 @@ class NetworkTests(test.TestCase):
|
|||||||
AndReturn([self.subnets.first()])
|
AndReturn([self.subnets.first()])
|
||||||
api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id).\
|
api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id).\
|
||||||
AndRaise(self.exceptions.quantum)
|
AndRaise(self.exceptions.quantum)
|
||||||
|
# Called from SubnetTable
|
||||||
|
api.quantum.network_get(IsA(http.HttpRequest), network_id).\
|
||||||
|
AndReturn(self.networks.first())
|
||||||
|
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
@ -402,8 +409,12 @@ class NetworkTests(test.TestCase):
|
|||||||
def test_delete_network_no_subnet(self):
|
def test_delete_network_no_subnet(self):
|
||||||
network = self.networks.first()
|
network = self.networks.first()
|
||||||
api.quantum.network_list(IsA(http.HttpRequest),
|
api.quantum.network_list(IsA(http.HttpRequest),
|
||||||
tenant_id=network.tenant_id)\
|
tenant_id=network.tenant_id,
|
||||||
|
shared=False)\
|
||||||
.AndReturn([network])
|
.AndReturn([network])
|
||||||
|
api.quantum.network_list(IsA(http.HttpRequest),
|
||||||
|
shared=True)\
|
||||||
|
.AndReturn([])
|
||||||
api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network.id)\
|
api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network.id)\
|
||||||
.AndReturn([])
|
.AndReturn([])
|
||||||
api.quantum.network_delete(IsA(http.HttpRequest), network.id)
|
api.quantum.network_delete(IsA(http.HttpRequest), network.id)
|
||||||
@ -423,8 +434,11 @@ class NetworkTests(test.TestCase):
|
|||||||
network = self.networks.first()
|
network = self.networks.first()
|
||||||
subnet = self.subnets.first()
|
subnet = self.subnets.first()
|
||||||
api.quantum.network_list(IsA(http.HttpRequest),
|
api.quantum.network_list(IsA(http.HttpRequest),
|
||||||
tenant_id=network.tenant_id)\
|
tenant_id=network.tenant_id,
|
||||||
|
shared=False)\
|
||||||
.AndReturn([network])
|
.AndReturn([network])
|
||||||
|
api.quantum.network_list(IsA(http.HttpRequest), shared=True)\
|
||||||
|
.AndReturn([])
|
||||||
api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network.id)\
|
api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network.id)\
|
||||||
.AndReturn([subnet])
|
.AndReturn([subnet])
|
||||||
api.quantum.subnet_delete(IsA(http.HttpRequest), subnet.id)
|
api.quantum.subnet_delete(IsA(http.HttpRequest), subnet.id)
|
||||||
@ -445,8 +459,12 @@ class NetworkTests(test.TestCase):
|
|||||||
network = self.networks.first()
|
network = self.networks.first()
|
||||||
subnet = self.subnets.first()
|
subnet = self.subnets.first()
|
||||||
api.quantum.network_list(IsA(http.HttpRequest),
|
api.quantum.network_list(IsA(http.HttpRequest),
|
||||||
tenant_id=network.tenant_id)\
|
tenant_id=network.tenant_id,
|
||||||
|
shared=False)\
|
||||||
.AndReturn([network])
|
.AndReturn([network])
|
||||||
|
api.quantum.network_list(IsA(http.HttpRequest),
|
||||||
|
shared=True)\
|
||||||
|
.AndReturn([])
|
||||||
api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network.id)\
|
api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network.id)\
|
||||||
.AndReturn([subnet])
|
.AndReturn([subnet])
|
||||||
api.quantum.subnet_delete(IsA(http.HttpRequest), subnet.id)
|
api.quantum.subnet_delete(IsA(http.HttpRequest), subnet.id)
|
||||||
@ -686,6 +704,7 @@ class NetworkTests(test.TestCase):
|
|||||||
|
|
||||||
@test.create_stubs({api.quantum: ('subnet_delete',
|
@test.create_stubs({api.quantum: ('subnet_delete',
|
||||||
'subnet_list',
|
'subnet_list',
|
||||||
|
'network_get',
|
||||||
'port_list',)})
|
'port_list',)})
|
||||||
def test_subnet_delete(self):
|
def test_subnet_delete(self):
|
||||||
subnet = self.subnets.first()
|
subnet = self.subnets.first()
|
||||||
@ -693,8 +712,13 @@ class NetworkTests(test.TestCase):
|
|||||||
api.quantum.subnet_delete(IsA(http.HttpRequest), subnet.id)
|
api.quantum.subnet_delete(IsA(http.HttpRequest), subnet.id)
|
||||||
api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network_id)\
|
api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network_id)\
|
||||||
.AndReturn([self.subnets.first()])
|
.AndReturn([self.subnets.first()])
|
||||||
|
api.quantum.network_get(IsA(http.HttpRequest), network_id)\
|
||||||
|
.AndReturn(self.networks.first())
|
||||||
api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id)\
|
api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id)\
|
||||||
.AndReturn([self.ports.first()])
|
.AndReturn([self.ports.first()])
|
||||||
|
# Called from SubnetTable
|
||||||
|
api.quantum.network_get(IsA(http.HttpRequest), network_id)\
|
||||||
|
.AndReturn(self.networks.first())
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
formData = {'action': 'subnets__delete__%s' % subnet.id}
|
formData = {'action': 'subnets__delete__%s' % subnet.id}
|
||||||
@ -706,16 +730,22 @@ class NetworkTests(test.TestCase):
|
|||||||
|
|
||||||
@test.create_stubs({api.quantum: ('subnet_delete',
|
@test.create_stubs({api.quantum: ('subnet_delete',
|
||||||
'subnet_list',
|
'subnet_list',
|
||||||
|
'network_get',
|
||||||
'port_list',)})
|
'port_list',)})
|
||||||
def test_subnet_delete_exception(self):
|
def test_subnet_delete_excceeption(self):
|
||||||
subnet = self.subnets.first()
|
subnet = self.subnets.first()
|
||||||
network_id = subnet.network_id
|
network_id = subnet.network_id
|
||||||
api.quantum.subnet_delete(IsA(http.HttpRequest), subnet.id)\
|
api.quantum.subnet_delete(IsA(http.HttpRequest), subnet.id)\
|
||||||
.AndRaise(self.exceptions.quantum)
|
.AndRaise(self.exceptions.quantum)
|
||||||
api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network_id)\
|
api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network_id)\
|
||||||
.AndReturn([self.subnets.first()])
|
.AndReturn([self.subnets.first()])
|
||||||
|
api.quantum.network_get(IsA(http.HttpRequest), network_id)\
|
||||||
|
.AndReturn(self.networks.first())
|
||||||
api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id)\
|
api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id)\
|
||||||
.AndReturn([self.ports.first()])
|
.AndReturn([self.ports.first()])
|
||||||
|
# Called from SubnetTable
|
||||||
|
api.quantum.network_get(IsA(http.HttpRequest), network_id)\
|
||||||
|
.AndReturn(self.networks.first())
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
formData = {'action': 'subnets__delete__%s' % subnet.id}
|
formData = {'action': 'subnets__delete__%s' % subnet.id}
|
||||||
|
@ -44,12 +44,9 @@ class IndexView(tables.DataTableView):
|
|||||||
|
|
||||||
def get_data(self):
|
def get_data(self):
|
||||||
try:
|
try:
|
||||||
# If a user has admin role, network list returned by Quantum API
|
|
||||||
# contains networks that does not belong to that tenant.
|
|
||||||
# So we need to specify tenant_id when calling network_list().
|
|
||||||
tenant_id = self.request.user.tenant_id
|
tenant_id = self.request.user.tenant_id
|
||||||
networks = api.quantum.network_list(self.request,
|
networks = api.quantum.network_list_for_tenant(self.request,
|
||||||
tenant_id=tenant_id)
|
tenant_id)
|
||||||
except:
|
except:
|
||||||
networks = []
|
networks = []
|
||||||
msg = _('Network list can not be retrieved.')
|
msg = _('Network list can not be retrieved.')
|
||||||
@ -104,9 +101,9 @@ class DetailView(tables.MultiTableView):
|
|||||||
|
|
||||||
def get_subnets_data(self):
|
def get_subnets_data(self):
|
||||||
try:
|
try:
|
||||||
network_id = self.kwargs['network_id']
|
network = self._get_data()
|
||||||
subnets = api.quantum.subnet_list(self.request,
|
subnets = api.quantum.subnet_list(self.request,
|
||||||
network_id=network_id)
|
network_id=network.id)
|
||||||
except:
|
except:
|
||||||
subnets = []
|
subnets = []
|
||||||
msg = _('Subnet list can not be retrieved.')
|
msg = _('Subnet list can not be retrieved.')
|
||||||
|
@ -24,8 +24,6 @@ from horizon import exceptions
|
|||||||
from horizon import forms
|
from horizon import forms
|
||||||
from horizon import messages
|
from horizon import messages
|
||||||
|
|
||||||
from horizon.dashboards.nova.networks import forms as user_forms
|
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -35,6 +33,8 @@ class CreateNetwork(forms.SelfHandlingForm):
|
|||||||
label=_("Name"),
|
label=_("Name"),
|
||||||
required=False)
|
required=False)
|
||||||
tenant_id = forms.ChoiceField(label=_("Project"))
|
tenant_id = forms.ChoiceField(label=_("Project"))
|
||||||
|
shared = forms.BooleanField(label=_("Shared"),
|
||||||
|
initial=False, required=False)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _instantiate(cls, request, *args, **kwargs):
|
def _instantiate(cls, request, *args, **kwargs):
|
||||||
@ -52,7 +52,8 @@ class CreateNetwork(forms.SelfHandlingForm):
|
|||||||
try:
|
try:
|
||||||
network = api.quantum.network_create(request,
|
network = api.quantum.network_create(request,
|
||||||
name=data['name'],
|
name=data['name'],
|
||||||
tenant_id=data['tenant_id'])
|
tenant_id=data['tenant_id'],
|
||||||
|
shared=data['shared'])
|
||||||
msg = _('Network %s was successfully created.') % data['name']
|
msg = _('Network %s was successfully created.') % data['name']
|
||||||
LOG.debug(msg)
|
LOG.debug(msg)
|
||||||
messages.success(request, msg)
|
messages.success(request, msg)
|
||||||
@ -63,5 +64,26 @@ class CreateNetwork(forms.SelfHandlingForm):
|
|||||||
exceptions.handle(request, msg, redirect=redirect)
|
exceptions.handle(request, msg, redirect=redirect)
|
||||||
|
|
||||||
|
|
||||||
class UpdateNetwork(user_forms.UpdateNetwork):
|
class UpdateNetwork(forms.SelfHandlingForm):
|
||||||
|
name = forms.CharField(label=_("Name"), required=False)
|
||||||
|
tenant_id = forms.CharField(widget=forms.HiddenInput)
|
||||||
|
network_id = forms.CharField(label=_("ID"),
|
||||||
|
widget=forms.TextInput(
|
||||||
|
attrs={'readonly': 'readonly'}))
|
||||||
|
shared = forms.BooleanField(label=_("Shared"), required=False)
|
||||||
failure_url = 'horizon:syspanel:networks:index'
|
failure_url = 'horizon:syspanel:networks:index'
|
||||||
|
|
||||||
|
def handle(self, request, data):
|
||||||
|
try:
|
||||||
|
network = api.quantum.network_modify(request, data['network_id'],
|
||||||
|
name=data['name'],
|
||||||
|
shared=data['shared'])
|
||||||
|
msg = _('Network %s was successfully updated.') % data['name']
|
||||||
|
LOG.debug(msg)
|
||||||
|
messages.success(request, msg)
|
||||||
|
return network
|
||||||
|
except:
|
||||||
|
msg = _('Failed to update network %s') % data['name']
|
||||||
|
LOG.info(msg)
|
||||||
|
redirect = reverse(self.failure_url)
|
||||||
|
exceptions.handle(request, msg, redirect=redirect)
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
|
from django.template import defaultfilters as filters
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from horizon import api
|
from horizon import api
|
||||||
@ -68,6 +69,8 @@ class NetworksTable(tables.DataTable):
|
|||||||
link='horizon:syspanel:networks:detail')
|
link='horizon:syspanel:networks:detail')
|
||||||
subnets = tables.Column(get_subnets,
|
subnets = tables.Column(get_subnets,
|
||||||
verbose_name=_("Subnets Associated"),)
|
verbose_name=_("Subnets Associated"),)
|
||||||
|
shared = tables.Column("shared", verbose_name=_("Shared"),
|
||||||
|
filters=(filters.yesno, filters.capfirst))
|
||||||
status = tables.Column("status", verbose_name=_("Status"))
|
status = tables.Column("status", verbose_name=_("Status"))
|
||||||
admin_state = tables.Column("admin_state",
|
admin_state = tables.Column("admin_state",
|
||||||
verbose_name=_("Admin State"))
|
verbose_name=_("Admin State"))
|
||||||
|
@ -167,12 +167,13 @@ class NetworkTests(test.BaseAdminViewTests):
|
|||||||
api.keystone.tenant_list(IsA(http.HttpRequest), admin=True)\
|
api.keystone.tenant_list(IsA(http.HttpRequest), admin=True)\
|
||||||
.AndReturn(tenants)
|
.AndReturn(tenants)
|
||||||
api.quantum.network_create(IsA(http.HttpRequest), name=network.name,
|
api.quantum.network_create(IsA(http.HttpRequest), name=network.name,
|
||||||
tenant_id=tenant_id)\
|
tenant_id=tenant_id, shared=True)\
|
||||||
.AndReturn(network)
|
.AndReturn(network)
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
form_data = {'tenant_id': tenant_id,
|
form_data = {'tenant_id': tenant_id,
|
||||||
'name': network.name}
|
'name': network.name,
|
||||||
|
'shared': True}
|
||||||
url = reverse('horizon:syspanel:networks:create')
|
url = reverse('horizon:syspanel:networks:create')
|
||||||
res = self.client.post(url, form_data)
|
res = self.client.post(url, form_data)
|
||||||
|
|
||||||
@ -188,12 +189,13 @@ class NetworkTests(test.BaseAdminViewTests):
|
|||||||
api.keystone.tenant_list(IsA(http.HttpRequest), admin=True)\
|
api.keystone.tenant_list(IsA(http.HttpRequest), admin=True)\
|
||||||
.AndReturn(tenants)
|
.AndReturn(tenants)
|
||||||
api.quantum.network_create(IsA(http.HttpRequest), name=network.name,
|
api.quantum.network_create(IsA(http.HttpRequest), name=network.name,
|
||||||
tenant_id=tenant_id)\
|
tenant_id=tenant_id, shared=False)\
|
||||||
.AndRaise(self.exceptions.quantum)
|
.AndRaise(self.exceptions.quantum)
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
form_data = {'tenant_id': tenant_id,
|
form_data = {'tenant_id': tenant_id,
|
||||||
'name': network.name}
|
'name': network.name,
|
||||||
|
'shared': False}
|
||||||
url = reverse('horizon:syspanel:networks:create')
|
url = reverse('horizon:syspanel:networks:create')
|
||||||
res = self.client.post(url, form_data)
|
res = self.client.post(url, form_data)
|
||||||
|
|
||||||
@ -232,7 +234,7 @@ class NetworkTests(test.BaseAdminViewTests):
|
|||||||
def test_network_update_post(self):
|
def test_network_update_post(self):
|
||||||
network = self.networks.first()
|
network = self.networks.first()
|
||||||
api.quantum.network_modify(IsA(http.HttpRequest), network.id,
|
api.quantum.network_modify(IsA(http.HttpRequest), network.id,
|
||||||
name=network.name)\
|
name=network.name, shared=True)\
|
||||||
.AndReturn(network)
|
.AndReturn(network)
|
||||||
api.quantum.network_get(IsA(http.HttpRequest), network.id)\
|
api.quantum.network_get(IsA(http.HttpRequest), network.id)\
|
||||||
.AndReturn(network)
|
.AndReturn(network)
|
||||||
@ -240,7 +242,8 @@ class NetworkTests(test.BaseAdminViewTests):
|
|||||||
|
|
||||||
formData = {'network_id': network.id,
|
formData = {'network_id': network.id,
|
||||||
'name': network.name,
|
'name': network.name,
|
||||||
'tenant_id': network.tenant_id}
|
'tenant_id': network.tenant_id,
|
||||||
|
'shared': True}
|
||||||
url = reverse('horizon:syspanel:networks:update', args=[network.id])
|
url = reverse('horizon:syspanel:networks:update', args=[network.id])
|
||||||
res = self.client.post(url, formData)
|
res = self.client.post(url, formData)
|
||||||
|
|
||||||
@ -251,7 +254,7 @@ class NetworkTests(test.BaseAdminViewTests):
|
|||||||
def test_network_update_post_exception(self):
|
def test_network_update_post_exception(self):
|
||||||
network = self.networks.first()
|
network = self.networks.first()
|
||||||
api.quantum.network_modify(IsA(http.HttpRequest), network.id,
|
api.quantum.network_modify(IsA(http.HttpRequest), network.id,
|
||||||
name=network.name)\
|
name=network.name, shared=False)\
|
||||||
.AndRaise(self.exceptions.quantum)
|
.AndRaise(self.exceptions.quantum)
|
||||||
api.quantum.network_get(IsA(http.HttpRequest), network.id)\
|
api.quantum.network_get(IsA(http.HttpRequest), network.id)\
|
||||||
.AndReturn(network)
|
.AndReturn(network)
|
||||||
@ -259,7 +262,8 @@ class NetworkTests(test.BaseAdminViewTests):
|
|||||||
|
|
||||||
form_data = {'network_id': network.id,
|
form_data = {'network_id': network.id,
|
||||||
'name': network.name,
|
'name': network.name,
|
||||||
'tenant_id': network.tenant_id}
|
'tenant_id': network.tenant_id,
|
||||||
|
'shared': False}
|
||||||
url = reverse('horizon:syspanel:networks:update', args=[network.id])
|
url = reverse('horizon:syspanel:networks:update', args=[network.id])
|
||||||
res = self.client.post(url, form_data)
|
res = self.client.post(url, form_data)
|
||||||
|
|
||||||
|
@ -131,3 +131,10 @@ class UpdateView(user_views.UpdateView):
|
|||||||
form_class = UpdateNetwork
|
form_class = UpdateNetwork
|
||||||
template_name = 'syspanel/networks/update.html'
|
template_name = 'syspanel/networks/update.html'
|
||||||
success_url = reverse_lazy('horizon:syspanel:networks:index')
|
success_url = reverse_lazy('horizon:syspanel:networks:index')
|
||||||
|
|
||||||
|
def get_initial(self):
|
||||||
|
network = self._get_object()
|
||||||
|
return {'network_id': network['id'],
|
||||||
|
'tenant_id': network['tenant_id'],
|
||||||
|
'name': network['name'],
|
||||||
|
'shared': network['shared']}
|
||||||
|
@ -36,7 +36,8 @@ def data(TEST):
|
|||||||
'name': 'net1',
|
'name': 'net1',
|
||||||
'status': 'ACTIVE',
|
'status': 'ACTIVE',
|
||||||
'subnets': ['e8abc972-eb0c-41f1-9edd-4bc6e3bcd8c9'],
|
'subnets': ['e8abc972-eb0c-41f1-9edd-4bc6e3bcd8c9'],
|
||||||
'tenant_id': '1'}
|
'tenant_id': '1',
|
||||||
|
'shared': False}
|
||||||
subnet_dict = {'allocation_pools': [{'end': '10.0.0.254',
|
subnet_dict = {'allocation_pools': [{'end': '10.0.0.254',
|
||||||
'start': '10.0.0.2'}],
|
'start': '10.0.0.2'}],
|
||||||
'cidr': '10.0.0.0/24',
|
'cidr': '10.0.0.0/24',
|
||||||
@ -75,7 +76,8 @@ def data(TEST):
|
|||||||
'name': 'net2',
|
'name': 'net2',
|
||||||
'status': 'ACTIVE',
|
'status': 'ACTIVE',
|
||||||
'subnets': ['3f7c5d79-ee55-47b0-9213-8e669fb03009'],
|
'subnets': ['3f7c5d79-ee55-47b0-9213-8e669fb03009'],
|
||||||
'tenant_id': '2'}
|
'tenant_id': '2',
|
||||||
|
'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'}],
|
||||||
'cidr': '172.16.88.0/24',
|
'cidr': '172.16.88.0/24',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user