adding aggregates panel to admin dashboard

This commit adds a new panel "Aggregates" to the admin panel in
the dashboard listing defined aggregates.

fixes bug #1197775

Change-Id: I19c00cf393844199acc1b0eb93e10c35099627a6
This commit is contained in:
Christian Berendt 2013-07-09 11:01:13 +02:00
parent 699926413c
commit 07b134334f
12 changed files with 257 additions and 2 deletions

View File

@ -620,3 +620,11 @@ def availability_zone_list(request, detailed=False):
def service_list(request):
return novaclient(request).services.list()
def aggregate_list(request):
result = []
for aggregate in novaclient(request).aggregates.list():
result.append(novaclient(request).aggregates.get(aggregate.id))
return result

View File

@ -0,0 +1,29 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 B1 Systems GmbH
#
# 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 Aggregates(horizon.Panel):
name = _("Aggregates")
slug = 'aggregates'
permissions = ('openstack.roles.admin',)
dashboard.Admin.register(Aggregates)

View File

@ -0,0 +1,54 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 B1 Systems GmbH
#
# 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 template
from django.utils.translation import ugettext_lazy as _
from horizon import tables
LOG = logging.getLogger(__name__)
def get_hosts(aggregate):
template_name = 'admin/aggregates/_aggregate_hosts.html'
context = {"aggregate": aggregate}
return template.loader.render_to_string(template_name, context)
def get_metadata(aggregate):
template_name = 'admin/aggregates/_aggregate_metadata.html'
context = {"aggregate": aggregate}
return template.loader.render_to_string(template_name, context)
class AdminAggregatesTable(tables.DataTable):
name = tables.Column("name",
verbose_name=_("Name"))
availability_zone = tables.Column("availability_zone",
verbose_name=_("Availability Zone"))
hosts = tables.Column(get_hosts,
verbose_name=_("Hosts"))
metadata = tables.Column(get_metadata,
verbose_name=_("Metadata"))
class Meta:
name = "aggregates"
verbose_name = _("Aggregates")

View File

@ -0,0 +1,5 @@
<ul>
{% for host in aggregate.hosts %}
<li>{{ host }}</li>
{% endfor %}
</ul>

View File

@ -0,0 +1,5 @@
<ul>
{% for key, value in aggregate.metadata.iteritems %}
<li>{{ key }} = {{ value }}</li>
{% endfor %}
</ul>

View File

@ -0,0 +1,11 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Aggregates" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("All Aggregates") %}
{% endblock page_header %}
{% block main %}
{{ table.render }}
{% endblock %}

View File

@ -0,0 +1,34 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 B1 Systems GmbH
#
# 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 django import http
from mox import IsA
from openstack_dashboard import api
from openstack_dashboard.test import helpers as test
class AggregateViewTest(test.BaseAdminViewTests):
@test.create_stubs({api.nova: ('aggregate_list',)})
def test_index(self):
aggregates = self.aggregates.list()
api.nova.aggregate_list(IsA(http.HttpRequest)).AndReturn(aggregates)
self.mox.ReplayAll()
res = self.client.get(reverse('horizon:admin:aggregates:index'))
self.assertTemplateUsed(res, 'admin/aggregates/index.html')
self.assertItemsEqual(res.context['table'].data, aggregates)

View File

@ -0,0 +1,27 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 B1 Systems GmbH
#
# 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
from django.conf.urls.defaults import url
from openstack_dashboard.dashboards.admin.aggregates.views \
import AdminIndexView
urlpatterns = patterns(
'openstack_dashboard.dashboards.admin.aggregates.views',
url(r'^$', AdminIndexView.as_view(), name='index')
)

View File

@ -0,0 +1,42 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 B1 Systems GmbH
#
# 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_lazy as _
from horizon import exceptions
from horizon import tables
from openstack_dashboard import api
from openstack_dashboard.dashboards.admin.aggregates.tables import \
AdminAggregatesTable
LOG = logging.getLogger(__name__)
class AdminIndexView(tables.DataTableView):
table_class = AdminAggregatesTable
template_name = 'admin/aggregates/index.html'
def get_data(self):
aggregates = []
try:
aggregates = api.nova.aggregate_list(self.request)
except:
exceptions.handle(self.request,
_('Unable to retrieve aggregate list.'))
return aggregates

View File

@ -22,8 +22,8 @@ import horizon
class SystemPanels(horizon.PanelGroup):
slug = "admin"
name = _("System Panel")
panels = ('overview', 'hypervisors', 'instances', 'volumes', 'flavors',
'images', 'networks', 'routers', 'info')
panels = ('overview', 'aggregates', 'hypervisors', 'instances', 'volumes',
'flavors', 'images', 'networks', 'routers', 'info')
class IdentityPanels(horizon.PanelGroup):

View File

@ -15,6 +15,7 @@
import json
import uuid
from novaclient.v1_1 import aggregates
from novaclient.v1_1 import availability_zones
from novaclient.v1_1 import certs
from novaclient.v1_1 import flavors
@ -166,6 +167,7 @@ def data(TEST):
TEST.availability_zones = TestDataContainer()
TEST.hypervisors = TestDataContainer()
TEST.services = TestDataContainer()
TEST.aggregates = TestDataContainer()
# Data return by novaclient.
# It is used if API layer does data conversion.
@ -541,3 +543,41 @@ def data(TEST):
)
TEST.services.add(service_1)
TEST.services.add(service_2)
# Aggregates
aggregate_1 = aggregates.Aggregate(aggregates.AggregateManager(None),
{
"name": "foo",
"availability_zone": None,
"deleted": 0,
"created_at": "2013-07-04T13:34:38.000000",
"updated_at": None,
"hosts": ["foo", "bar"],
"deleted_at": None,
"id": 1,
"metadata": {
"foo": "testing",
"bar": "testing"
}
}
)
aggregate_2 = aggregates.Aggregate(aggregates.AggregateManager(None),
{
"name": "bar",
"availability_zone": "testing",
"deleted": 0,
"created_at": "2013-07-04T13:34:38.000000",
"updated_at": None,
"hosts": ["foo", "bar"],
"deleted_at": None,
"id": 2,
"metadata": {
"foo": "testing",
"bar": "testing"
}
}
)
TEST.aggregates.add(aggregate_1)
TEST.aggregates.add(aggregate_2)