diff --git a/horizon/api/__init__.py b/horizon/api/__init__.py index b2b1d2437..3e37214df 100644 --- a/horizon/api/__init__.py +++ b/horizon/api/__init__.py @@ -36,4 +36,3 @@ from horizon.api.glance import * from horizon.api.keystone import * from horizon.api.nova import * from horizon.api.swift import * -from horizon.api.quantum import * diff --git a/horizon/api/quantum.py b/horizon/api/quantum.py deleted file mode 100644 index 10e4a9d83..000000000 --- a/horizon/api/quantum.py +++ /dev/null @@ -1,132 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -from __future__ import absolute_import - -import logging -import urlparse - -from quantum import client as quantum_client - -from horizon.api.base import url_for -from horizon.api import nova - - -LOG = logging.getLogger(__name__) - - -# FIXME(gabriel): Add object wrappers for Quantum client. The quantum client -# returns plain dicts (a la Glance) which we should wrap. - -def quantum_api(request): - tenant = request.user.tenant_id - url = urlparse.urlparse(url_for(request, 'network')) - return quantum_client.Client(url.hostname, url.port, False, tenant, 'json') - - -def quantum_list_networks(request): - return quantum_api(request).list_networks() - - -def quantum_network_details(request, network_id): - return quantum_api(request).show_network_details(network_id) - - -def quantum_list_ports(request, network_id): - return quantum_api(request).list_ports(network_id) - - -def quantum_port_details(request, network_id, port_id): - return quantum_api(request).show_port_details(network_id, port_id) - - -def quantum_create_network(request, data): - return quantum_api(request).create_network(data) - - -def quantum_delete_network(request, network_id): - return quantum_api(request).delete_network(network_id) - - -def quantum_update_network(request, network_id, data): - return quantum_api(request).update_network(network_id, data) - - -def quantum_create_port(request, network_id): - return quantum_api(request).create_port(network_id) - - -def quantum_delete_port(request, network_id, port_id): - return quantum_api(request).delete_port(network_id, port_id) - - -def quantum_attach_port(request, network_id, port_id, data): - return quantum_api(request).attach_resource(network_id, port_id, data) - - -def quantum_detach_port(request, network_id, port_id): - return quantum_api(request).detach_resource(network_id, port_id) - - -def quantum_set_port_state(request, network_id, port_id, data): - return quantum_api(request).update_port(network_id, port_id, data) - - -def quantum_port_attachment(request, network_id, port_id): - return quantum_api(request).show_port_attachment(network_id, port_id) - - -def get_vif_ids(request): - vifs = [] - attached_vifs = [] - # Get a list of all networks - networks_list = quantum_api(request).list_networks() - for network in networks_list['networks']: - ports = quantum_api(request).list_ports(network['id']) - # Get port attachments - for port in ports['ports']: - port_attachment = quantum_api(request).show_port_attachment( - network['id'], - port['id']) - if port_attachment['attachment']: - attached_vifs.append( - port_attachment['attachment']['id'].encode('ascii')) - # Get all instances - instances = nova.server_list(request) - # Get virtual interface ids by instance - for instance in instances: - id = instance.id - instance_vifs = nova.virtual_interfaces_list(request, id) - for vif in instance_vifs: - # Check if this VIF is already connected to any port - if str(vif.id) in attached_vifs: - vifs.append({ - 'id': vif.id, - 'instance': instance.id, - 'instance_name': instance.name, - 'available': False}) - else: - vifs.append({ - 'id': vif.id, - 'instance': instance.id, - 'instance_name': instance.name, - 'available': True}) - return vifs diff --git a/horizon/dashboards/nova/dashboard.py b/horizon/dashboards/nova/dashboard.py index 31fac520f..c47742bdf 100644 --- a/horizon/dashboards/nova/dashboard.py +++ b/horizon/dashboards/nova/dashboard.py @@ -26,7 +26,6 @@ class Nova(horizon.Dashboard): 'instances_and_volumes', 'access_and_security', 'images_and_snapshots'), - _("Network"): ('networks',), _("Object Store"): ('containers',)} default_panel = 'overview' supports_tenants = True diff --git a/horizon/dashboards/nova/networks/__init__.py b/horizon/dashboards/nova/networks/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/horizon/dashboards/nova/networks/forms.py b/horizon/dashboards/nova/networks/forms.py deleted file mode 100644 index a48d1157f..000000000 --- a/horizon/dashboards/nova/networks/forms.py +++ /dev/null @@ -1,131 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging - -from django import shortcuts -from django.contrib import messages -from django.utils.translation import ugettext as _ - -from horizon import api -from horizon import exceptions -from horizon import forms - - -LOG = logging.getLogger(__name__) - - -class CreateNetwork(forms.SelfHandlingForm): - name = forms.CharField(required=True, label=_("Network Name")) - - def handle(self, request, data): - network_name = data['name'] - try: - data = {'network': {'name': network_name}} - api.quantum.quantum_create_network(request, data) - messages.success(request, - _('Network %s has been created.') % network_name) - except: - exceptions.handle(request, _("Unable to create network.")) - return shortcuts.redirect('horizon:nova:networks:index') - - -class RenameNetwork(forms.SelfHandlingForm): - network = forms.CharField(widget=forms.HiddenInput()) - new_name = forms.CharField(required=True) - - def handle(self, request, data): - try: - LOG.info('Renaming network %s to %s' % - (data['network'], data['new_name'])) - send_data = {'network': {'name': '%s' % data['new_name']}} - api.quantum_update_network(request, data['network'], send_data) - except Exception, e: - if not hasattr(e, 'message'): - e.message = str(e) - messages.error(request, - _('Unable to rename network %(network)s: %(msg)s') % - {"network": data['network'], "msg": e.message}) - else: - msg = _('Network %(net)s has been renamed to %(new_name)s.') % { - "net": data['network'], "new_name": data['new_name']} - LOG.info(msg) - messages.success(request, msg) - - return shortcuts.redirect('horizon:nova:networks:index') - - -class CreatePort(forms.SelfHandlingForm): - network = forms.CharField(widget=forms.HiddenInput()) - ports_num = forms.IntegerField(required=True, label=_("Number of Ports")) - - def handle(self, request, data): - try: - LOG.info('Creating %s ports on network %s' % - (data['ports_num'], data['network'])) - for i in range(0, data['ports_num']): - api.quantum_create_port(request, data['network']) - except Exception, e: - if not hasattr(e, 'message'): - e.message = str(e) - messages.error(request, - _('Unable to create ports on network %(network)s: %(msg)s') % - {"network": data['network'], "msg": e.message}) - else: - msg = _('%(num_ports)s ports created on network %(network)s.') % { - "num_ports": data['ports_num'], "network": data['network']} - LOG.info(msg) - messages.success(request, msg) - - return shortcuts.redirect('horizon:nova:networks:detail', - network_id=data['network']) - - -class AttachPort(forms.SelfHandlingForm): - network = forms.CharField(widget=forms.HiddenInput()) - port = forms.CharField(widget=forms.HiddenInput()) - vif_id = forms.ChoiceField(label=_("Select VIF to connect")) - - def __init__(self, request, *args, **kwargs): - super(AttachPort, self).__init__(*args, **kwargs) - # Populate VIF choices - vif_choices = [('', "Select a VIF")] - for vif in api.get_vif_ids(request): - if vif['available']: - name = "Instance %s VIF %s" % (vif['instance_name'], vif['id']) - vif_choices.append((vif['id'], name,)) - self.fields['vif_id'].choices = vif_choices - - @classmethod - def _instantiate(cls, request, *args, **kwargs): - return cls(request, *args, **kwargs) - - def handle(self, request, data): - try: - body = {'attachment': {'id': '%s' % data['vif_id']}} - api.quantum_attach_port(request, - data['network'], - data['port'], - body) - messages.success(request, _("Port attached.")) - except: - exceptions.handle(request, _('Unable to attach port.')) - return shortcuts.redirect("horizon:nova:networks:detail", - data['network']) diff --git a/horizon/dashboards/nova/networks/panel.py b/horizon/dashboards/nova/networks/panel.py deleted file mode 100644 index 529339f64..000000000 --- a/horizon/dashboards/nova/networks/panel.py +++ /dev/null @@ -1,31 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import horizon -from horizon.dashboards.nova import dashboard - - -class Networks(horizon.Panel): - name = "Networks" - slug = 'networks' - services = ("network",) - - -dashboard.Nova.register(Networks) diff --git a/horizon/dashboards/nova/networks/tables.py b/horizon/dashboards/nova/networks/tables.py deleted file mode 100644 index 7fa906b61..000000000 --- a/horizon/dashboards/nova/networks/tables.py +++ /dev/null @@ -1,118 +0,0 @@ -import logging - -from django.core.urlresolvers import reverse -from django.utils.translation import ugettext_lazy as _ - -from horizon import api -from horizon import tables - - -LOG = logging.getLogger(__name__) - - -class RenameNetworkLink(tables.LinkAction): - name = "rename_network" - verbose_name = _("Rename Network") - url = "horizon:nova:networks:rename" - attrs = {"class": "ajax-modal"} - - -class CreateNetworkLink(tables.LinkAction): - name = "create_network" - verbose_name = _("Create New Network") - url = "horizon:nova:networks:create" - classes = ("ajax-modal",) - - -class DeleteNetworkAction(tables.DeleteAction): - data_type_singular = _("Network") - data_type_plural = _("Networks") - - def delete(self, request, obj_id): - api.quantum_delete_network(request, obj_id) - - -class NetworksTable(tables.DataTable): - id = tables.Column('id', verbose_name=_('Network Id'), - link="horizon:nova:networks:detail") - name = tables.Column('name', verbose_name=_('Name')) - used = tables.Column('used', verbose_name=_('Used')) - available = tables.Column('available', verbose_name=_('Available')) - total = tables.Column('total', verbose_name=_('Total')) - #tenant = tables.Column('tenant', verbose_name=_('Project')) - - def get_object_id(self, datum): - return datum['id'] - - def get_object_display(self, obj): - return obj['name'] - - class Meta: - name = "networks" - verbose_name = _("Networks") - row_actions = (DeleteNetworkAction, RenameNetworkLink,) - table_actions = (CreateNetworkLink, DeleteNetworkAction,) - - -class CreatePortLink(tables.LinkAction): - name = "create_port" - verbose_name = _("Create Ports") - url = "horizon:nova:networks:port_create" - classes = ("ajax-modal",) - - def get_link_url(self, datum=None): - network_id = self.table.kwargs['network_id'] - return reverse(self.url, args=(network_id,)) - - -class DeletePortAction(tables.DeleteAction): - data_type_singular = _("Port") - data_type_plural = _("Ports") - - def delete(self, request, obj_id): - api.quantum_delete_port(request, - self.table.kwargs['network_id'], - obj_id) - - -class DetachPortAction(tables.BatchAction): - name = "detach_port" - action_present = _("Detach") - action_past = _("Detached") - data_type_singular = _("Port") - data_type_plural = _("Ports") - - def action(self, request, datum_id): - body = {'port': {'state': 'DOWN'}} - api.quantum_set_port_state(request, - self.table.kwargs['network_id'], - datum_id, body) - - -class AttachPortAction(tables.LinkAction): - name = "attach_port" - verbose_name = _("Attach Port") - url = "horizon:nova:networks:port_attach" - attrs = {"class": "ajax-modal"} - - def get_link_url(self, datum=None): - network_id = self.table.kwargs['network_id'] - return reverse(self.url, args=(network_id, datum['id'])) - - -class NetworkDetailsTable(tables.DataTable): - id = tables.Column('id', verbose_name=_('Port Id')) - state = tables.Column('state', verbose_name=_('State')) - attachment = tables.Column('attachment', verbose_name=_('Attachment')) - - def get_object_id(self, datum): - return datum['id'] - - def get_object_display(self, obj): - return obj['id'] - - class Meta: - name = "network_details" - verbose_name = _("Network Port Details") - row_actions = (DeletePortAction, AttachPortAction, DetachPortAction) - table_actions = (CreatePortLink, DeletePortAction,) diff --git a/horizon/dashboards/nova/networks/tests.py b/horizon/dashboards/nova/networks/tests.py deleted file mode 100644 index c1283cab2..000000000 --- a/horizon/dashboards/nova/networks/tests.py +++ /dev/null @@ -1,295 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from django import http -from django.core.urlresolvers import reverse -from mox import IsA - -from horizon import api -from horizon import test - - -class NetworkViewTests(test.TestCase): - def setUp(self): - super(NetworkViewTests, self).setUp() - # TODO(gabriel): Move this to horizon.tests.test_data.quantum_data - # after the wrapper classes are added for Quantum. - self.network = {} - self.network['networks'] = [] - self.network['networks'].append({'id': 'n1'}) - self.network_details = {'network': {'id': '1', 'name': 'test_network'}} - self.ports = {} - self.ports['ports'] = [] - self.ports['ports'].append({'id': 'p1'}) - self.port_details = { - 'port': { - 'id': 'p1', - 'state': 'DOWN'}} - self.port_attachment = { - 'attachment': { - 'id': 'vif1'}} - self.vifs = [{'id': 'vif1'}] - - def test_network_index(self): - self.mox.StubOutWithMock(api, 'quantum_list_networks') - api.quantum_list_networks(IsA(http.HttpRequest)).\ - AndReturn(self.network) - - self.mox.StubOutWithMock(api, 'quantum_network_details') - api.quantum_network_details(IsA(http.HttpRequest), - 'n1').AndReturn(self.network_details) - - self.mox.StubOutWithMock(api, 'quantum_list_ports') - api.quantum_list_ports(IsA(http.HttpRequest), - 'n1').AndReturn(self.ports) - - self.mox.StubOutWithMock(api, 'quantum_port_attachment') - api.quantum_port_attachment(IsA(http.HttpRequest), - 'n1', 'p1').AndReturn(self.port_attachment) - - self.mox.ReplayAll() - - res = self.client.get(reverse('horizon:nova:networks:index')) - - self.assertTemplateUsed(res, 'nova/networks/index.html') - networks = res.context['table'].data - - self.assertEqual(len(networks), 1) - self.assertEqual(networks[0]['name'], 'test_network') - self.assertEqual(networks[0]['id'], 'n1') - self.assertEqual(networks[0]['total'], 1) - self.assertEqual(networks[0]['used'], 1) - self.assertEqual(networks[0]['available'], 0) - - def test_network_create(self): - self.mox.StubOutWithMock(api.quantum, "quantum_create_network") - api.quantum.quantum_create_network(IsA(http.HttpRequest), - IsA(dict)).AndReturn(True) - - self.mox.ReplayAll() - - formData = {'name': 'Test', - 'method': 'CreateNetwork'} - - res = self.client.post(reverse('horizon:nova:networks:create'), - formData) - - self.assertRedirectsNoFollow(res, - reverse('horizon:nova:networks:index')) - - def test_network_delete(self): - self.mox.StubOutWithMock(api, "quantum_delete_network") - api.quantum_delete_network(IsA(http.HttpRequest), 'n1').AndReturn(True) - - self.mox.StubOutWithMock(api, 'quantum_list_networks') - api.quantum_list_networks(IsA(http.HttpRequest)).\ - AndReturn(self.network) - - self.mox.StubOutWithMock(api, 'quantum_network_details') - api.quantum_network_details(IsA(http.HttpRequest), - 'n1').AndReturn(self.network_details) - - self.mox.StubOutWithMock(api, 'quantum_list_ports') - api.quantum_list_ports(IsA(http.HttpRequest), - 'n1').AndReturn(self.ports) - - self.mox.StubOutWithMock(api, 'quantum_port_attachment') - api.quantum_port_attachment(IsA(http.HttpRequest), - 'n1', 'p1').AndReturn(self.port_attachment) - - self.mox.ReplayAll() - - formData = {'action': 'networks__delete__n1'} - - self.client.post(reverse('horizon:nova:networks:index'), formData) - - def test_network_rename(self): - self.mox.StubOutWithMock(api, 'quantum_network_details') - api.quantum_network_details(IsA(http.HttpRequest), - 'n1').AndReturn(self.network_details) - - self.mox.StubOutWithMock(api, 'quantum_update_network') - api.quantum_update_network(IsA(http.HttpRequest), 'n1', - {'network': {'name': "Test1"}}) - - self.mox.ReplayAll() - - formData = {'network': 'n1', - 'new_name': 'Test1', - 'method': 'RenameNetwork'} - - res = self.client.post(reverse('horizon:nova:networks:rename', - args=["n1"]), - formData) - - self.assertRedirectsNoFollow(res, - reverse('horizon:nova:networks:index')) - - def test_network_details(self): - self.mox.StubOutWithMock(api, 'quantum_network_details') - api.quantum_network_details(IsA(http.HttpRequest), - 'n1').AndReturn(self.network_details) - - self.mox.StubOutWithMock(api, 'quantum_list_ports') - api.quantum_list_ports(IsA(http.HttpRequest), - 'n1').AndReturn(self.ports) - - self.mox.StubOutWithMock(api, 'quantum_port_attachment') - api.quantum_port_attachment(IsA(http.HttpRequest), - 'n1', 'p1').AndReturn(self.port_attachment) - - self.mox.StubOutWithMock(api, 'quantum_port_details') - api.quantum_port_details(IsA(http.HttpRequest), - 'n1', 'p1').AndReturn(self.port_details) - - self.mox.StubOutWithMock(api, 'get_vif_ids') - api.get_vif_ids(IsA(http.HttpRequest)).AndReturn(self.vifs) - - self.mox.ReplayAll() - - res = self.client.get(reverse('horizon:nova:networks:detail', - args=['n1'])) - - self.assertTemplateUsed(res, 'nova/networks/detail.html') - self.assertIn('network', res.context) - - network = res.context['network'] - - self.assertEqual(network['name'], 'test_network') - self.assertEqual(network['id'], 'n1') - - def test_port_create(self): - self.mox.StubOutWithMock(api, "quantum_network_details") - self.mox.StubOutWithMock(api, "quantum_create_port") - network_details = {'network': {'id': 'n1'}} - api.quantum_network_details(IsA(http.HttpRequest), - 'n1').AndReturn(network_details) - api.quantum_create_port(IsA(http.HttpRequest), 'n1').AndReturn(True) - - formData = {'ports_num': 1, - 'network': 'n1', - 'method': 'CreatePort'} - - self.mox.ReplayAll() - - res = self.client.post(reverse('horizon:nova:networks:port_create', - args=["n1"]), - formData) - - self.assertRedirectsNoFollow(res, - reverse('horizon:nova:networks:detail', - args=["n1"])) - - def test_port_delete(self): - self.mox.StubOutWithMock(api, 'quantum_network_details') - self.mox.StubOutWithMock(api, 'quantum_list_ports') - self.mox.StubOutWithMock(api, 'quantum_port_attachment') - self.mox.StubOutWithMock(api, 'quantum_port_details') - self.mox.StubOutWithMock(api, 'get_vif_ids') - self.mox.StubOutWithMock(api, "quantum_delete_port") - network_details = {'network': {'id': 'n1', 'name': 'network1'}} - api.quantum_network_details(IsA(http.HttpRequest), - 'n1').AndReturn(network_details) - - api.quantum_list_ports(IsA(http.HttpRequest), - 'n1').AndReturn(self.ports) - - api.quantum_port_attachment(IsA(http.HttpRequest), - 'n1', 'p1').AndReturn(self.port_attachment) - - api.quantum_port_details(IsA(http.HttpRequest), - 'n1', 'p1').AndReturn(self.port_details) - - api.get_vif_ids(IsA(http.HttpRequest)).AndReturn(self.vifs) - - api.quantum_delete_port(IsA(http.HttpRequest), - 'n1', 'p1').AndReturn(True) - - formData = {'action': 'network_details__delete__p1'} - - self.mox.ReplayAll() - - detail_url = reverse('horizon:nova:networks:detail', args=["n1"]) - self.client.post(detail_url, formData) - - def test_port_attach(self): - self.mox.StubOutWithMock(api, "quantum_network_details") - self.mox.StubOutWithMock(api, "quantum_attach_port") - self.mox.StubOutWithMock(api, "get_vif_ids") - network_details = {'network': {'id': 'n1'}} - api.quantum_network_details(IsA(http.HttpRequest), - 'n1').AndReturn(network_details) - api.quantum_attach_port(IsA(http.HttpRequest), - 'n1', 'p1', IsA(dict)).AndReturn(True) - api.get_vif_ids(IsA(http.HttpRequest)).AndReturn([{ - 'id': 'v1', - 'instance_name': 'instance1', - 'available': True}]) - - formData = {'port': 'p1', - 'network': 'n1', - 'vif_id': 'v1', - 'method': 'AttachPort'} - - self.mox.ReplayAll() - - res = self.client.post(reverse('horizon:nova:networks:port_attach', - args=["n1", "p1"]), - formData) - - self.assertRedirectsNoFollow(res, - reverse('horizon:nova:networks:detail', - args=["n1"])) - - def test_port_detach(self): - self.mox.StubOutWithMock(api, 'quantum_network_details') - self.mox.StubOutWithMock(api, 'quantum_list_ports') - self.mox.StubOutWithMock(api, 'quantum_port_attachment') - self.mox.StubOutWithMock(api, 'quantum_port_details') - self.mox.StubOutWithMock(api, 'get_vif_ids') - self.mox.StubOutWithMock(api, "quantum_set_port_state") - network_details = {'network': {'id': 'n1', 'name': 'network1'}} - api.quantum_network_details(IsA(http.HttpRequest), - 'n1').AndReturn(network_details) - - api.quantum_list_ports(IsA(http.HttpRequest), - 'n1').AndReturn(self.ports) - - api.quantum_port_attachment(IsA(http.HttpRequest), - 'n1', 'p1').AndReturn(self.port_attachment) - - api.quantum_port_details(IsA(http.HttpRequest), - 'n1', 'p1').AndReturn(self.port_details) - - api.get_vif_ids(IsA(http.HttpRequest)).AndReturn(self.vifs) - - api.quantum_set_port_state(IsA(http.HttpRequest), - 'n1', - 'p1', - {'port': {'state': 'DOWN'}}).AndReturn(True) - - formData = {'action': "network_details__detach_port__p1"} - - self.mox.ReplayAll() - - detail_url = reverse('horizon:nova:networks:detail', args=["n1"]) - res = self.client.post(detail_url, formData) - - self.assertRedirectsNoFollow(res, detail_url) diff --git a/horizon/dashboards/nova/networks/urls.py b/horizon/dashboards/nova/networks/urls.py deleted file mode 100644 index fb01572b8..000000000 --- a/horizon/dashboards/nova/networks/urls.py +++ /dev/null @@ -1,36 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from django.conf.urls.defaults import patterns, url - -from .views import (IndexView, CreateView, RenameView, - DetailView, CreatePortView, AttachPortView) - -urlpatterns = patterns('horizon.dashboards.nova.networks.views', - url(r'^$', IndexView.as_view(), name='index'), - url(r'^create/$', CreateView.as_view(), name='create'), - url(r'^(?P[^/]+)/detail/$', DetailView.as_view(), - name='detail'), - url(r'^(?P[^/]+)/rename/$', RenameView.as_view(), - name='rename'), - url(r'^(?P[^/]+)/ports/create/$', CreatePortView.as_view(), - name='port_create'), - url(r'^(?P[^/]+)/ports/(?P[^/]+)/attach/$', - AttachPortView.as_view(), name='port_attach')) diff --git a/horizon/dashboards/nova/networks/views.py b/horizon/dashboards/nova/networks/views.py deleted file mode 100644 index 0523b95bd..000000000 --- a/horizon/dashboards/nova/networks/views.py +++ /dev/null @@ -1,212 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Views for managing Quantum networks. -""" - -import logging - -from django import http -from django.contrib import messages -from django.core.urlresolvers import reverse -from django.utils.translation import ugettext as _ - -from horizon import api -from horizon import exceptions -from horizon import forms -from horizon import tables -from horizon.dashboards.nova.networks.forms import (CreateNetwork, - RenameNetwork, AttachPort, CreatePort) -from .tables import NetworksTable, NetworkDetailsTable - - -LOG = logging.getLogger(__name__) - - -class IndexView(tables.DataTableView): - table_class = NetworksTable - template_name = 'nova/networks/index.html' - - def get_data(self): - tenant_id = self.request.user.tenant_id - networks = [] - - try: - networks_list = api.quantum_list_networks(self.request) - details = [] - for network in networks_list['networks']: - net_stats = _calc_network_stats(self.request, network['id']) - # Get network details like name and id - details = api.quantum_network_details(self.request, - network['id']) - networks.append({ - 'name': details['network']['name'], - 'id': network['id'], - 'total': net_stats['total'], - 'available': net_stats['available'], - 'used': net_stats['used'], - 'tenant': tenant_id}) - except Exception, e: - LOG.exception("Unable to get network list.") - if not hasattr(e, 'message'): - e.message = str(e) - messages.error(self.request, - _('Unable to get network list: %s') % e.message) - return networks - - -class CreateView(forms.ModalFormView): - form_class = CreateNetwork - template_name = 'nova/networks/create.html' - - -class RenameView(forms.ModalFormView): - form_class = RenameNetwork - template_name = 'nova/networks/rename.html' - context_object_name = 'network' - - def get_object(self, *args, **kwargs): - network_id = kwargs['network_id'] - try: - return api.quantum_network_details(self.request, - network_id)['network'] - except: - redirect = reverse("horizon:nova:networks:detail", - args=(network_id,)) - exceptions.handle(self.request, - _('Unable to retrieve network information.'), - redirect=redirect) - - def get_initial(self): - return {'network': self.object['id']} - - -class DetailView(tables.DataTableView): - table_class = NetworkDetailsTable - template_name = 'nova/networks/detail.html' - - def get_data(self): - network_id = self.kwargs['network_id'] - network_details = api.quantum_network_details(self.request, network_id) - self.network = {'id': network_id, - 'name': network_details['network']['name'], - 'ports': _get_port_states(self.request, network_id)} - return self.network['ports'] - - def get_context_data(self, **kwargs): - context = super(DetailView, self).get_context_data(**kwargs) - context['network'] = self.network - return context - - -def _get_port_states(request, network_id): - """ - Helper method to find port states for a network - """ - network_ports = [] - # Get all vifs for comparison with port attachments - vifs = api.get_vif_ids(request) - - # Get all ports on this network - ports = api.quantum_list_ports(request, network_id) - for port in ports['ports']: - port_details = api.quantum_port_details(request, - network_id, port['id']) - # Get port attachments - port_attachment = api.quantum_port_attachment(request, - network_id, port['id']) - # Find instance the attachment belongs to - connected_instance = None - if port_attachment['attachment']: - for vif in vifs: - if str(vif['id']) == str(port_attachment['attachment']['id']): - connected_instance = vif['id'] - break - network_ports.append({ - 'id': port_details['port']['id'], - 'state': port_details['port']['state'], - 'attachment': port_attachment['attachment'], - 'instance': connected_instance}) - return network_ports - - -def _calc_network_stats(request, network_id): - """ - Helper method to calculate statistics for a network - """ - # Get all ports statistics for the network - total = 0 - available = 0 - used = 0 - ports = api.quantum_list_ports(request, network_id) - for port in ports['ports']: - total += 1 - # Get port attachment - port_attachment = api.quantum_port_attachment(request, - network_id, port['id']) - if port_attachment['attachment']: - used += 1 - else: - available += 1 - - return {'total': total, 'used': used, 'available': available} - - -class CreatePortView(forms.ModalFormView): - form_class = CreatePort - template_name = 'nova/networks/ports/create.html' - context_object_name = 'port' - - def get_object(self, *args, **kwargs): - network_id = kwargs['network_id'] - try: - return api.quantum_network_details(self.request, - network_id)['network'] - except: - redirect = reverse("horizon:nova:networks:detail", - args=(network_id,)) - exceptions.handle(self.request, - _('Unable to retrieve network information.'), - redirect=redirect) - - def get_initial(self): - return {'network': self.object['id']} - - -class AttachPortView(forms.ModalFormView): - form_class = AttachPort - template_name = 'nova/networks/ports/attach.html' - context_object_name = 'network' - - def get_object(self, *args, **kwargs): - network_id = kwargs['network_id'] - try: - return api.quantum_network_details(self.request, - network_id)['network'] - except: - redirect = reverse("horizon:nova:networks:detail", - args=(network_id,)) - exceptions.handle(self.request, - _('Unable to attach port.'), - redirect=redirect) - - def get_initial(self): - return {'network': self.object['id']} diff --git a/horizon/dashboards/nova/templates/nova/networks/_create.html b/horizon/dashboards/nova/templates/nova/networks/_create.html deleted file mode 100644 index d5617ae14..000000000 --- a/horizon/dashboards/nova/templates/nova/networks/_create.html +++ /dev/null @@ -1,24 +0,0 @@ -{% extends "horizon/common/_modal_form.html" %} -{% load i18n %} - -{% block form_id %}create_network_form{% endblock %} -{% block form_action %}{% url horizon:nova:networks:create %}{% endblock %} - -{% block modal-header %}Create Network{% endblock %} - -{% block modal-body %} -
-
- {% include "horizon/common/_form_fields.html" %} -
-
-
-

{% trans "Description" %}:

-

{% trans "Networks provide layer 2 connectivity to your instances." %}

-
-{% endblock %} - -{% block modal-footer %} - - {% trans "Cancel" %} -{% endblock %} diff --git a/horizon/dashboards/nova/templates/nova/networks/_rename.html b/horizon/dashboards/nova/templates/nova/networks/_rename.html deleted file mode 100644 index 13b2a836f..000000000 --- a/horizon/dashboards/nova/templates/nova/networks/_rename.html +++ /dev/null @@ -1,24 +0,0 @@ -{% extends "horizon/common/_modal_form.html" %} -{% load i18n %} - -{% block form_id %}form_rename_{{ network.id }}{% endblock %} -{% block form_action %}{% url horizon:nova:networks:rename network.id %}{% endblock %} - -{% block modal-header %}Rename Network{% endblock %} - -{% block modal-body %} -
-
- {% include "horizon/common/_form_fields.html" %} -
-
-
-

{% trans "Rename" %}:

-

{% trans "Enter a new name for your network." %}

-
-{% endblock %} - -{% block modal-footer %} - - {% trans "Cancel" %} -{% endblock %} diff --git a/horizon/dashboards/nova/templates/nova/networks/create.html b/horizon/dashboards/nova/templates/nova/networks/create.html deleted file mode 100644 index 7ee658dfa..000000000 --- a/horizon/dashboards/nova/templates/nova/networks/create.html +++ /dev/null @@ -1,13 +0,0 @@ -{% extends 'nova/base.html' %} -{% load i18n %} -{% block title %}Create Network{% endblock %} - -{% block page_header %} - {# to make searchable false, just remove it from the include statement #} - {% include "horizon/common/_page_header.html" with title=_("Create Network") %} -{% endblock page_header %} - -{% block dash_main %} - {% include 'nova/networks/_create.html' with form=network_form %} -{% endblock %} - diff --git a/horizon/dashboards/nova/templates/nova/networks/detail.html b/horizon/dashboards/nova/templates/nova/networks/detail.html deleted file mode 100644 index daa7e1bf7..000000000 --- a/horizon/dashboards/nova/templates/nova/networks/detail.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'nova/base.html' %} -{% load i18n %} -{% block title %}{% trans "Network Detail" %}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title=network.name %} -{% endblock page_header %} - -{% block dash_main %} - {{ table.render }} -{% endblock %} diff --git a/horizon/dashboards/nova/templates/nova/networks/index.html b/horizon/dashboards/nova/templates/nova/networks/index.html deleted file mode 100644 index 302014252..000000000 --- a/horizon/dashboards/nova/templates/nova/networks/index.html +++ /dev/null @@ -1,13 +0,0 @@ -{% extends 'nova/base.html' %} -{% load i18n %} -{% block title %}Networks{% endblock %} - -{% block page_header %} - {% url horizon:nova:networks:index as refresh_link %} - {# to make searchable false, just remove it from the include statement #} - {% include "horizon/common/_page_header.html" with title=_("Networks") refresh_link=refresh_link searchable="true" %} -{% endblock page_header %} - -{% block dash_main %} - {{ table.render }} -{% endblock %} diff --git a/horizon/dashboards/nova/templates/nova/networks/rename.html b/horizon/dashboards/nova/templates/nova/networks/rename.html deleted file mode 100644 index e5bda3dfa..000000000 --- a/horizon/dashboards/nova/templates/nova/networks/rename.html +++ /dev/null @@ -1,13 +0,0 @@ -{% extends 'nova/base.html' %} -{% load i18n %} -{% block title %}Rename Network{% endblock %} - -{% block page_header %} - {# to make searchable false, just remove it from the include statement #} - {% include "horizon/common/_page_header.html" with title=_("Rename Network") %} -{% endblock page_header %} - -{% block dash_main %} - {% include 'nova/networks/_rename.html' with form=rename_form %} -{% endblock %} - diff --git a/horizon/tests/test_data/quantum_data.py b/horizon/tests/test_data/quantum_data.py deleted file mode 100644 index 0471c08d4..000000000 --- a/horizon/tests/test_data/quantum_data.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from .utils import TestDataContainer - - -def data(TEST): - TEST.networks = TestDataContainer() - TEST.ports = TestDataContainer() - # TODO(gabriel): Move quantum test data into this module after it - # has been refactored with object wrappers (a la Glance). diff --git a/tools/pip-requires b/tools/pip-requires index 929fd3b59..22f00385f 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -20,5 +20,4 @@ iso8601 # Horizon Non-pip Requirements -e git+https://github.com/openstack/python-novaclient.git#egg=python-novaclient -e git+https://github.com/openstack/python-keystoneclient.git#egg=python-keystoneclient --e git+https://github.com/openstack/python-quantumclient.git#egg=python-quantumclient -e git+https://github.com/openstack/glance.git#egg=glance