diff --git a/openstack_dashboard/api/nova.py b/openstack_dashboard/api/nova.py
index 68a0d2f21d..822645753a 100644
--- a/openstack_dashboard/api/nova.py
+++ b/openstack_dashboard/api/nova.py
@@ -183,7 +183,8 @@ def novaclient(request):
request.user.token.id,
project_id=request.user.tenant_id,
auth_url=url_for(request, 'compute'),
- insecure=insecure)
+ insecure=insecure,
+ http_log_debug=settings.DEBUG)
c.client.auth_token = request.user.token.id
c.client.management_url = url_for(request, 'compute')
return c
diff --git a/openstack_dashboard/dashboards/admin/dashboard.py b/openstack_dashboard/dashboards/admin/dashboard.py
index 5eaf66f8cb..e556f97e3c 100644
--- a/openstack_dashboard/dashboards/admin/dashboard.py
+++ b/openstack_dashboard/dashboards/admin/dashboard.py
@@ -22,8 +22,8 @@ import horizon
class SystemPanels(horizon.PanelGroup):
slug = "admin"
name = _("System Panel")
- panels = ('overview', 'instances', 'volumes', 'services', 'flavors',
- 'images', 'projects', 'users', 'quotas', 'networks',)
+ panels = ('overview', 'instances', 'volumes', 'flavors',
+ 'images', 'projects', 'users', 'networks', 'info')
class Admin(horizon.Dashboard):
diff --git a/openstack_dashboard/dashboards/admin/quotas/__init__.py b/openstack_dashboard/dashboards/admin/info/__init__.py
similarity index 100%
rename from openstack_dashboard/dashboards/admin/quotas/__init__.py
rename to openstack_dashboard/dashboards/admin/info/__init__.py
diff --git a/openstack_dashboard/dashboards/admin/quotas/panel.py b/openstack_dashboard/dashboards/admin/info/panel.py
similarity index 95%
rename from openstack_dashboard/dashboards/admin/quotas/panel.py
rename to openstack_dashboard/dashboards/admin/info/panel.py
index 266f6af2b1..6c0508cccc 100644
--- a/openstack_dashboard/dashboards/admin/quotas/panel.py
+++ b/openstack_dashboard/dashboards/admin/info/panel.py
@@ -26,8 +26,8 @@ from openstack_dashboard.dashboards.admin import dashboard
class Quotas(horizon.Panel):
- name = _("Quotas")
- slug = 'quotas'
+ name = _("System Info")
+ slug = 'info'
dashboard.Admin.register(Quotas)
diff --git a/openstack_dashboard/dashboards/admin/services/tables.py b/openstack_dashboard/dashboards/admin/info/tables.py
similarity index 65%
rename from openstack_dashboard/dashboards/admin/services/tables.py
rename to openstack_dashboard/dashboards/admin/info/tables.py
index fd9aa8cad0..42f7060f7e 100644
--- a/openstack_dashboard/dashboards/admin/services/tables.py
+++ b/openstack_dashboard/dashboards/admin/info/tables.py
@@ -1,6 +1,5 @@
import logging
-from django import template
from django.utils.translation import ugettext_lazy as _
from horizon import tables
@@ -9,6 +8,36 @@ from horizon import tables
LOG = logging.getLogger(__name__)
+class QuotaFilterAction(tables.FilterAction):
+ def filter(self, table, tenants, filter_string):
+ q = filter_string.lower()
+
+ def comp(tenant):
+ if q in tenant.name.lower():
+ return True
+ return False
+
+ return filter(comp, tenants)
+
+
+def get_quota_name(quota):
+ return quota.name.replace("_", " ").title()
+
+
+class QuotasTable(tables.DataTable):
+ name = tables.Column(get_quota_name, verbose_name=_('Quota Name'))
+ limit = tables.Column("limit", verbose_name=_('Limit'))
+
+ def get_object_id(self, obj):
+ return obj.name
+
+ class Meta:
+ name = "quotas"
+ verbose_name = _("Quotas")
+ table_actions = (QuotaFilterAction,)
+ multi_select = False
+
+
class ServiceFilterAction(tables.FilterAction):
def filter(self, table, services, filter_string):
q = filter_string.lower()
diff --git a/openstack_dashboard/dashboards/admin/info/tabs.py b/openstack_dashboard/dashboards/admin/info/tabs.py
new file mode 100644
index 0000000000..33d9adedb5
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/info/tabs.py
@@ -0,0 +1,62 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import tabs
+
+from openstack_dashboard.api import keystone
+from openstack_dashboard.usage import quotas
+from .tables import QuotasTable, ServicesTable
+
+
+class DefaultQuotasTab(tabs.TableTab):
+ table_classes = (QuotasTable,)
+ name = _("Default Quotas")
+ slug = "quotas"
+ template_name = ("horizon/common/_detail_table.html")
+
+ def get_quotas_data(self):
+ request = self.tab_group.request
+ try:
+ quota_set = quotas.get_default_quota_data(request)
+ data = quota_set.items
+ except:
+ data = []
+ exceptions.handle(self.request, _('Unable to get quota info.'))
+ return data
+
+
+class ServicesTab(tabs.TableTab):
+ table_classes = (ServicesTable,)
+ name = _("Services")
+ slug = "services"
+ template_name = ("horizon/common/_detail_table.html")
+
+ def get_services_data(self):
+ request = self.tab_group.request
+ services = []
+ for i, service in enumerate(request.user.service_catalog):
+ service['id'] = i
+ services.append(keystone.Service(service))
+ return services
+
+
+class SystemInfoTabs(tabs.TabGroup):
+ slug = "system_info"
+ tabs = (ServicesTab, DefaultQuotasTab,)
+ sticky = True
diff --git a/openstack_dashboard/dashboards/admin/info/templates/info/index.html b/openstack_dashboard/dashboards/admin/info/templates/info/index.html
new file mode 100644
index 0000000000..a947ae3884
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/info/templates/info/index.html
@@ -0,0 +1,15 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "System Info" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("System Info")%}
+{% endblock page_header %}
+
+{% block main %}
+
+
+ {{ tab_group.render }}
+
+
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/info/tests.py b/openstack_dashboard/dashboards/admin/info/tests.py
new file mode 100644
index 0000000000..6938d8b827
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/info/tests.py
@@ -0,0 +1,71 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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 openstack_dashboard.test import helpers as test
+from openstack_dashboard import api
+
+INDEX_URL = reverse('horizon:admin:info:index')
+
+
+class ServicessViewTests(test.BaseAdminViewTests):
+ def test_index(self):
+ self.mox.StubOutWithMock(api.nova, 'default_quota_get')
+ self.mox.StubOutWithMock(api.cinder, 'default_quota_get')
+ api.nova.default_quota_get(IsA(http.HttpRequest),
+ self.tenant.id).AndReturn(self.quotas.nova)
+ api.cinder.default_quota_get(IsA(http.HttpRequest), self.tenant.id) \
+ .AndReturn(self.quotas.nova)
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(INDEX_URL)
+
+ self.assertTemplateUsed(res, 'admin/info/index.html')
+
+ services_tab = res.context['tab_group'].get_tab('services')
+ self.assertQuerysetEqual(services_tab._tables['services'].data,
+ ['',
+ '',
+ '',
+ '',
+ '',
+ '',
+ ''])
+
+ quotas_tab = res.context['tab_group'].get_tab('quotas')
+ self.assertQuerysetEqual(quotas_tab._tables['quotas'].data,
+ ['',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ ''])
diff --git a/openstack_dashboard/dashboards/admin/quotas/urls.py b/openstack_dashboard/dashboards/admin/info/urls.py
similarity index 92%
rename from openstack_dashboard/dashboards/admin/quotas/urls.py
rename to openstack_dashboard/dashboards/admin/info/urls.py
index 33871bce00..9c46de826f 100644
--- a/openstack_dashboard/dashboards/admin/quotas/urls.py
+++ b/openstack_dashboard/dashboards/admin/info/urls.py
@@ -23,5 +23,5 @@ from django.conf.urls.defaults import patterns, url
from .views import IndexView
-urlpatterns = patterns('openstack_dashboard.dashboards.admin.quotas.views',
+urlpatterns = patterns('openstack_dashboard.dashboards.admin.info.views',
url(r'^$', IndexView.as_view(), name='index'))
diff --git a/openstack_dashboard/dashboards/admin/services/urls.py b/openstack_dashboard/dashboards/admin/info/views.py
similarity index 77%
rename from openstack_dashboard/dashboards/admin/services/urls.py
rename to openstack_dashboard/dashboards/admin/info/views.py
index b5a5c9cd3e..d0f7f8f0b4 100644
--- a/openstack_dashboard/dashboards/admin/services/urls.py
+++ b/openstack_dashboard/dashboards/admin/info/views.py
@@ -18,10 +18,16 @@
# License for the specific language governing permissions and limitations
# under the License.
-from django.conf.urls.defaults import patterns, url
+import logging
-from .views import IndexView
+from horizon import tabs
+
+from .tabs import SystemInfoTabs
-urlpatterns = patterns('openstack_dashboard.dashboards.admin.services.views',
- url(r'^$', IndexView.as_view(), name='index'))
+LOG = logging.getLogger(__name__)
+
+
+class IndexView(tabs.TabbedTableView):
+ tab_group_class = SystemInfoTabs
+ template_name = 'admin/info/index.html'
diff --git a/openstack_dashboard/dashboards/admin/quotas/tables.py b/openstack_dashboard/dashboards/admin/quotas/tables.py
deleted file mode 100644
index 9ca936e36b..0000000000
--- a/openstack_dashboard/dashboards/admin/quotas/tables.py
+++ /dev/null
@@ -1,38 +0,0 @@
-import logging
-
-from django.utils.translation import ugettext_lazy as _
-
-from horizon import tables
-
-
-LOG = logging.getLogger(__name__)
-
-
-class QuotaFilterAction(tables.FilterAction):
- def filter(self, table, tenants, filter_string):
- q = filter_string.lower()
-
- def comp(tenant):
- if q in tenant.name.lower():
- return True
- return False
-
- return filter(comp, tenants)
-
-
-def get_quota_name(quota):
- return quota.name.replace("_", " ").title()
-
-
-class QuotasTable(tables.DataTable):
- name = tables.Column(get_quota_name, verbose_name=_('Quota Name'))
- limit = tables.Column("limit", verbose_name=_('Limit'))
-
- def get_object_id(self, obj):
- return obj.name
-
- class Meta:
- name = "quotas"
- verbose_name = _("Quotas")
- table_actions = (QuotaFilterAction,)
- multi_select = False
diff --git a/openstack_dashboard/dashboards/admin/quotas/templates/quotas/index.html b/openstack_dashboard/dashboards/admin/quotas/templates/quotas/index.html
deleted file mode 100644
index 0650cf021e..0000000000
--- a/openstack_dashboard/dashboards/admin/quotas/templates/quotas/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-{% block title %}Quotas{% endblock %}
-
-{% block page_header %}
- {% url horizon:admin:quotas:index as refresh_link %}
- {# to make searchable false, just remove it from the include statement #}
- {% include "horizon/common/_page_header.html" with title=_("Default Quotas") refresh_link=refresh_link searchable="true" %}
-{% endblock page_header %}
-
-{% block main %}
- {{ table.render }}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/quotas/tests.py b/openstack_dashboard/dashboards/admin/quotas/tests.py
deleted file mode 100644
index adcf7d8d10..0000000000
--- a/openstack_dashboard/dashboards/admin/quotas/tests.py
+++ /dev/null
@@ -1 +0,0 @@
-#FIXME(gabriel): Needs tests!
diff --git a/openstack_dashboard/dashboards/admin/quotas/views.py b/openstack_dashboard/dashboards/admin/quotas/views.py
deleted file mode 100644
index 0d70d95b02..0000000000
--- a/openstack_dashboard/dashboards/admin/quotas/views.py
+++ /dev/null
@@ -1,47 +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.utils.translation import ugettext as _
-
-from horizon import exceptions
-from horizon import tables
-
-from openstack_dashboard import api
-from .tables import QuotasTable
-
-
-LOG = logging.getLogger(__name__)
-
-
-class IndexView(tables.DataTableView):
- table_class = QuotasTable
- template_name = 'admin/quotas/index.html'
-
- def get_data(self):
- try:
- quota_set = api.default_quota_get(self.request,
- self.request.user.tenant_id)
- data = quota_set.items
- except:
- data = []
- exceptions.handle(self.request, _('Unable to get quota info.'))
- return data
diff --git a/openstack_dashboard/dashboards/admin/services/__init__.py b/openstack_dashboard/dashboards/admin/services/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/openstack_dashboard/dashboards/admin/services/panel.py b/openstack_dashboard/dashboards/admin/services/panel.py
deleted file mode 100644
index 622f37e23b..0000000000
--- a/openstack_dashboard/dashboards/admin/services/panel.py
+++ /dev/null
@@ -1,33 +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.utils.translation import ugettext_lazy as _
-
-import horizon
-
-from openstack_dashboard.dashboards.admin import dashboard
-
-
-class Services(horizon.Panel):
- name = _("Services")
- slug = 'services'
-
-
-dashboard.Admin.register(Services)
diff --git a/openstack_dashboard/dashboards/admin/services/templates/services/index.html b/openstack_dashboard/dashboards/admin/services/templates/services/index.html
deleted file mode 100644
index abfba78dd3..0000000000
--- a/openstack_dashboard/dashboards/admin/services/templates/services/index.html
+++ /dev/null
@@ -1,14 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-{% block title %}Services{% endblock %}
-
-{% block page_header %}
- {% url horizon:admin:services:index as refresh_link %}
- {# to make searchable false, just remove it from the include statement #}
- {% include "horizon/common/_page_header.html" with title=_("Services") refresh_link=refresh_link searchable="true" %}
-{% endblock page_header %}
-
-{% block main %}
- {{ table.render }}
-{% endblock %}
-
diff --git a/openstack_dashboard/dashboards/admin/services/tests.py b/openstack_dashboard/dashboards/admin/services/tests.py
deleted file mode 100644
index 15f5fa98f3..0000000000
--- a/openstack_dashboard/dashboards/admin/services/tests.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# 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.core.urlresolvers import reverse
-
-from openstack_dashboard.test import helpers as test
-
-
-INDEX_URL = reverse('horizon:admin:services:index')
-
-
-class ServicessViewTests(test.BaseAdminViewTests):
- def test_index(self):
- res = self.client.get(INDEX_URL)
- self.assertTemplateUsed(res, 'admin/services/index.html')
- self.assertQuerysetEqual(res.context['table'].data,
- ['',
- '',
- '',
- '',
- '',
- '',
- ''])
diff --git a/openstack_dashboard/dashboards/admin/services/views.py b/openstack_dashboard/dashboards/admin/services/views.py
deleted file mode 100644
index 3824685454..0000000000
--- a/openstack_dashboard/dashboards/admin/services/views.py
+++ /dev/null
@@ -1,41 +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 horizon import tables
-
-from openstack_dashboard import api
-from .tables import ServicesTable
-
-
-LOG = logging.getLogger(__name__)
-
-
-class IndexView(tables.DataTableView):
- table_class = ServicesTable
- template_name = 'admin/services/index.html'
-
- def get_data(self):
- services = []
- for i, service in enumerate(self.request.user.service_catalog):
- service['id'] = i
- services.append(api.keystone.Service(service))
- return services
diff --git a/openstack_dashboard/test/test_data/nova_data.py b/openstack_dashboard/test/test_data/nova_data.py
index 100215bb67..b3ccd96d75 100644
--- a/openstack_dashboard/test/test_data/nova_data.py
+++ b/openstack_dashboard/test/test_data/nova_data.py
@@ -280,6 +280,7 @@ def data(TEST):
injected_files='1',
cores='10')
quota = quotas.QuotaSet(quotas.QuotaSetManager(None), quota_data)
+ TEST.quotas.nova = QuotaSetWrapper(quota)
TEST.quotas.add(QuotaSetWrapper(quota))
# Quota Usages