Merge "Improve usability of syspanel instance list."

This commit is contained in:
Jenkins
2012-02-24 01:20:39 +00:00
committed by Gerrit Code Review
6 changed files with 95 additions and 7 deletions

View File

@@ -4,6 +4,7 @@
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
# Copyright 2012 Openstack, LLC
# Copyright 2012 Nebula, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -102,6 +103,10 @@ def keystoneclient(request, username=None, password=None, tenant_id=None,
return conn
def tenant_name(request, tenant_id):
return keystoneclient(request).tenants.get(tenant_id).name
def tenant_create(request, tenant_name, description, enabled):
return keystoneclient(request, admin=True).tenants.create(tenant_name,
description,

View File

@@ -4,6 +4,7 @@
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
# Copyright 2012 Openstack, LLC
# Copyright 2012 Nebula, Inc.
# Copyright (c) 2012 X.commerce, a business unit of eBay Inc.
#
@@ -27,6 +28,7 @@ from novaclient.v1_1 import client as nova_client
from novaclient.v1_1 import security_group_rules as nova_rules
from novaclient.v1_1.servers import REBOOT_HARD
from horizon.api import keystone
from horizon.api.base import APIResourceWrapper, APIDictWrapper, url_for
@@ -77,10 +79,12 @@ class Server(APIResourceWrapper):
Preserves the request info so image name can later be retrieved
"""
_attrs = ['addresses', 'attrs', 'hostId', 'id', 'image', 'links',
_attrs = ['addresses', 'attrs', 'id', 'image', 'links',
'metadata', 'name', 'private_ip', 'public_ip', 'status', 'uuid',
'image_name', 'VirtualInterfaces', 'flavor', 'key_name',
'OS-EXT-STS:power_state', 'OS-EXT-STS:task_state']
'tenant_id', 'user_id', 'OS-EXT-STS:power_state',
'OS-EXT-STS:task_state', 'OS-EXT-SRV-ATTR:instance_name',
'OS-EXT-SRV-ATTR:host']
def __init__(self, apiresource, request):
super(Server, self).__init__(apiresource)

View File

@@ -0,0 +1,67 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 Openstack, LLC
# 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 template
from django.template.defaultfilters import title
from django.utils.datastructures import SortedDict
from django.utils.translation import ugettext as _
from horizon import api
from horizon import tables
from horizon.dashboards.nova.instances_and_volumes.instances.tables import \
(LaunchLink, TerminateInstance, EditInstance, ConsoleLink, LogLink,
SnapshotLink, TogglePause, ToggleSuspend, RebootInstance, get_size,
TerminateInstance, UpdateRow, get_ips, get_power_state)
from horizon.templatetags import sizeformat
LOG = logging.getLogger(__name__)
class SyspanelInstancesTable(tables.DataTable):
TASK_STATUS_CHOICES = (
(None, True),
("none", True)
)
tenant = tables.Column("tenant_name", verbose_name=_("Tenant"))
user = tables.Column("user_id", verbose_name=_("User"))
internal_id = tables.Column("internal_identifier",
verbose_name=_("Instance ID"))
host = tables.Column("OS-EXT-SRV-ATTR:host", verbose_name=_("Host"))
name = tables.Column("name", link="horizon:nova:instances_and_volumes:" \
"instances:detail")
ip = tables.Column(get_ips, verbose_name=_("IP Address"))
size = tables.Column(get_size, verbose_name=_("Size"))
status = tables.Column("status", filters=(title,))
task = tables.Column("OS-EXT-STS:task_state",
verbose_name=_("Task"),
filters=(title,),
status=True,
status_choices=TASK_STATUS_CHOICES)
state = tables.Column(get_power_state,
filters=(title,),
verbose_name=_("Power State"))
class Meta:
name = "instances"
verbose_name = _("Instances")
status_column = "task"
table_actions = (LaunchLink, TerminateInstance)
row_actions = (EditInstance, ConsoleLink, LogLink, SnapshotLink,
TogglePause, ToggleSuspend, RebootInstance,
TerminateInstance, UpdateRow)

View File

@@ -27,8 +27,12 @@ class InstanceViewTest(test.BaseAdminViewTests):
def test_index(self):
servers = self.servers.list()
flavors = self.flavors.list()
tenants = self.tenants.list()
self.mox.StubOutWithMock(api.nova, 'server_list')
self.mox.StubOutWithMock(api.nova, 'flavor_list')
self.mox.StubOutWithMock(api.keystone, 'tenant_list')
api.keystone.tenant_list(IsA(http.HttpRequest), admin=True).\
AndReturn(tenants)
api.nova.server_list(IsA(http.HttpRequest),
all_tenants=True).AndReturn(servers)
api.nova.flavor_list(IsA(http.HttpRequest)).AndReturn(flavors)

View File

@@ -4,6 +4,7 @@
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
# Copyright 2012 Openstack, LLC
# Copyright 2012 Nebula, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -26,8 +27,7 @@ from django.utils.translation import ugettext as _
from horizon import api
from horizon import exceptions
from horizon import tables
from horizon.dashboards.nova.instances_and_volumes \
.instances.tables import InstancesTable
from horizon.dashboards.syspanel.instances.tables import SyspanelInstancesTable
from horizon.dashboards.nova.instances_and_volumes \
.instances.views import console, DetailView, vnc
@@ -36,7 +36,7 @@ LOG = logging.getLogger(__name__)
class AdminIndexView(tables.DataTableView):
table_class = InstancesTable
table_class = SyspanelInstancesTable
template_name = 'syspanel/instances/index.html'
def get_data(self):
@@ -49,10 +49,17 @@ class AdminIndexView(tables.DataTableView):
if instances:
try:
flavors = api.nova.flavor_list(self.request)
tenants = SortedDict([(str(tenant.id), tenant) for \
tenant in api.keystone.tenant_list(
self.request, admin=True)])
full_flavors = SortedDict([(str(flavor.id), flavor) for \
flavor in flavors])
for instance in instances:
instance.full_flavor = full_flavors[instance.flavor["id"]]
for inst in instances:
inst.full_flavor = full_flavors[inst.flavor["id"]]
inst.internal_identifier = "%s (%s)" % (inst.id,
getattr(inst, 'OS-EXT-SRV-ATTR:instance_name'))
inst.tenant_name = "%s (%s)" % (inst.tenant_id,
tenants[inst.tenant_id].name)
except:
msg = _('Unable to retrieve instance size information.')
exceptions.handle(self.request, msg)

View File

@@ -26,6 +26,7 @@ from .utils import TestDataContainer
SERVER_DATA = """
{
"server": {
"OS-EXT-SRV-ATTR:instance_name": "instance-00000005",
"OS-EXT-STS:task_state": null,
"addresses": {
"private": [