Merge "Improve usability of syspanel instance list."
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
67
horizon/horizon/dashboards/syspanel/instances/tables.py
Normal file
67
horizon/horizon/dashboards/syspanel/instances/tables.py
Normal 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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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": [
|
||||
|
||||
Reference in New Issue
Block a user