Merge branch 'master' of github.com:cloudbuilders/openstack-dashboard

This commit is contained in:
Jake Dahn
2011-07-09 01:11:48 -07:00
16 changed files with 187 additions and 21 deletions

View File

@@ -131,7 +131,7 @@ def server_delete(request, instance):
def server_get(request, instance_id): def server_get(request, instance_id):
return compute_api(request).servers.get(instance_id) return extras_api(request).servers.get(instance_id)
def server_list(request): def server_list(request):
@@ -143,6 +143,12 @@ def server_reboot(request, instance_id, hardness=openstack.compute.servers.REBOO
return server.reboot(hardness) return server.reboot(hardness)
def server_update(request, instance_id, name, description):
return extras_api(request).servers.update(instance_id,
name=name,
description=description)
def service_get(request, name): def service_get(request, name):
return admin_api(request).services.get(name) return admin_api(request).services.get(name)

View File

@@ -35,6 +35,9 @@ class Login(forms.SelfHandlingForm):
except api_exceptions.Unauthorized as e: except api_exceptions.Unauthorized as e:
messages.error(request, 'Error authenticating: %s' % e.message) messages.error(request, 'Error authenticating: %s' % e.message)
except api_exceptions.ApiException as e:
messages.error(request, 'Error authenticating with keystone: %s' %
e.message)
def login(request): def login(request):
@@ -68,6 +71,3 @@ def switch_tenants(request, tenant_id):
def logout(request): def logout(request):
request.session.clear() request.session.clear()
return shortcuts.redirect('splash') return shortcuts.redirect('splash')

View File

@@ -1,8 +1,15 @@
from django_openstack import api from django_openstack import api
from django.contrib import messages
from openstackx.api import exceptions as api_exceptions
def tenants(request): def tenants(request):
if not request.user or not request.user.is_authenticated(): if not request.user or not request.user.is_authenticated():
return {} return {}
return {'tenants': api.token_list_tenants(request, request.user.token)}
try:
return {'tenants': api.token_list_tenants(request, request.user.token)}
except api_exceptions.BadRequest, e:
messages.error(request, "Unable to retrieve tenant list from\
keystone: %s" % e.message)
return {'tenants': []}

View File

@@ -13,6 +13,7 @@ urlpatterns = patterns('django_openstack.dash.views.instances',
url(r'^(?P<tenant_id>[^/]+)/instances/refresh$', 'refresh', name='dash_instances_refresh'), url(r'^(?P<tenant_id>[^/]+)/instances/refresh$', 'refresh', name='dash_instances_refresh'),
url(INSTANCES % 'console', 'console', name='dash_instances_console'), url(INSTANCES % 'console', 'console', name='dash_instances_console'),
url(INSTANCES % 'vnc', 'vnc', name='dash_instances_vnc'), url(INSTANCES % 'vnc', 'vnc', name='dash_instances_vnc'),
url(INSTANCES % 'update', 'update', name='dash_instances_update'),
) )
urlpatterns += patterns('django_openstack.dash.views.images', urlpatterns += patterns('django_openstack.dash.views.images',

View File

@@ -114,7 +114,14 @@ class LaunchForm(forms.SelfHandlingForm):
@login_required @login_required
def index(request, tenant_id): def index(request, tenant_id):
tenant = api.token_get_tenant(request, request.user.tenant) tenant = {}
try:
tenant = api.token_get_tenant(request, request.user.tenant)
except api_exceptions.ApiException, e:
messages.error(request, "Unable to retrienve tenant info\
from keystone: %s" % e.message)
all_images = [] all_images = []
try: try:
all_images = api.image_list_detailed(request) all_images = api.image_list_detailed(request)
@@ -166,8 +173,19 @@ def launch(request, tenant_id, image_id):
except: except:
return [] return []
image = api.image_get(request, image_id) try:
tenant = api.token_get_tenant(request, request.user.tenant) image = api.image_get(request, image_id)
except Exception, e:
messages.error(request, 'Unable to retrieve image %s: %s' %
(image_id, e.message))
return redirect('dash_instances', tenant_id)
try:
tenant = api.token_get_tenant(request, request.user.tenant)
except api_exceptions.ApiException, e:
messages.error(request, 'Unable to retrieve tenant %s: %s' %
(request.user.tenant, e.message))
return redirect('dash_instances', tenant_id)
form, handled = LaunchForm.maybe_handle( form, handled = LaunchForm.maybe_handle(
request, initial={'flavorlist': flavorlist(), request, initial={'flavorlist': flavorlist(),

View File

@@ -74,6 +74,13 @@ class RebootInstance(forms.SelfHandlingForm):
return redirect(request.build_absolute_uri()) return redirect(request.build_absolute_uri())
class UpdateInstance(forms.Form):
instance = forms.CharField(widget=forms.TextInput(
attrs={'readonly':'readonly'}))
name = forms.CharField(required=True)
description = forms.CharField(required=False)
@login_required @login_required
def index(request, tenant_id): def index(request, tenant_id):
for f in (TerminateInstance, RebootInstance): for f in (TerminateInstance, RebootInstance):
@@ -208,3 +215,33 @@ def vnc(request, tenant_id, instance_id):
'Unable to get vnc console for instance %s: %s' % 'Unable to get vnc console for instance %s: %s' %
(instance_id, e.message)) (instance_id, e.message))
return redirect('dash_instances', tenant_id) return redirect('dash_instances', tenant_id)
@login_required
def update(request, tenant_id, instance_id):
if request.POST:
form = UpdateInstance(request.POST)
if form.is_valid():
data = form.clean()
instance_id = data['instance']
name = data['name']
description = data.get('description', '')
try:
api.server_update(request, instance_id, name, description)
messages.success(request, "Instance %s updated" % instance_id)
except api_exceptions.ApiException, e:
messages.error(request,
'Unable to update instance: %s' % e.message)
return redirect('dash_instances', tenant_id)
else:
instance = api.server_get(request, instance_id)
form = UpdateInstance(initial={'instance': instance_id,
'tenant_id': tenant_id,
'name': instance.name,
'description': instance.attrs['description']})
return render_to_response('dash_instance_update.html', {
'instance': instance,
'form': form,
}, context_instance=template.RequestContext(request))

View File

@@ -46,6 +46,10 @@ class AuthenticationMiddleware(object):
#BEWARE - had to add this exception handler #BEWARE - had to add this exception handler
# to make token expiration work # to make token expiration work
openstackx.api.exceptions.NotFound]: openstackx.api.exceptions.NotFound]:
# flush other error messages, which are collateral damage
# when our token expires
for message in messages.get_messages(request):
pass
messages.error(request, 'Your token has expired.\ messages.error(request, 'Your token has expired.\
Please log in again') Please log in again')
return shortcuts.redirect('/auth/logout') return shortcuts.redirect('/auth/logout')

View File

@@ -27,12 +27,12 @@ class AddUser(forms.SelfHandlingForm):
def handle(self, request, data): def handle(self, request, data):
try: try:
api.account_api(request).role_refs.add_for_tenant_user(data['tenant'], api.account_api(request).role_refs.add_for_tenant_user(data['tenant'],
data['user'], 'Member') data['user'], settings.OPENSTACK_KEYSTONE_DEFAULT_ROLE)
messages.success(request, messages.success(request,
'%s was successfully removed from %s.' '%s was successfully added to %s.'
% (data['user'], data['tenant'])) % (data['user'], data['tenant']))
except api_exceptions.ApiException, e: except api_exceptions.ApiException, e:
messages.error(request, 'Unable to create tenant: %s' % messages.error(request, 'Unable to create user association: %s' %
(e.message)) (e.message))
return redirect('syspanel_tenants') return redirect('syspanel_tenants')
@@ -154,10 +154,20 @@ def users(request, tenant_id):
users = api.account_api(request).users.get_for_tenant(tenant_id).values users = api.account_api(request).users.get_for_tenant(tenant_id).values
all_users = api.account_api(request).users.list() all_users = api.account_api(request).users.list()
new_user_ids = []
user_ids = [u['id'] for u in users]
all_user_ids = [u.id for u in all_users]
for uid in all_user_ids:
if not uid in user_ids:
new_user_ids.append(uid)
for i in user_ids:
if i in new_user_ids:
new_user_ids.remove(i)
return render_to_response( return render_to_response(
'syspanel_tenant_users.html',{ 'syspanel_tenant_users.html',{
'add_user_form': add_user_form, 'add_user_form': add_user_form,
'remove_user_form': remove_user_form, 'remove_user_form': remove_user_form,
'tenant_id': tenant_id, 'tenant_id': tenant_id,
'users': users, 'users': users,
'new_users': new_user_ids,
}, context_instance = template.RequestContext(request)) }, context_instance = template.RequestContext(request))

View File

@@ -39,9 +39,9 @@ class UserDeleteForm(forms.SelfHandlingForm):
def handle(self, request, data): def handle(self, request, data):
user_id = data['user'] user_id = data['user']
api.user_delete(request, user_id) api.user_delete(request, user_id)
messages.info(request, messages.info(request, '%s was successfully deleted.'
'%s was successfully deleted.' % user_id)
% user_id)
return redirect(request.build_absolute_uri()) return redirect(request.build_absolute_uri())
@@ -52,7 +52,12 @@ def index(request):
if handled: if handled:
return handled return handled
users = api.user_list(request) users = []
try:
users = api.user_list(request)
except api_exceptions.ApiException, e:
messages.error(request, 'Unable to list users: %s' %
e.message)
user_delete_form = UserDeleteForm() user_delete_form = UserDeleteForm()
return render_to_response('syspanel_users.html',{ return render_to_response('syspanel_users.html',{
@@ -119,7 +124,12 @@ def update(request, user_id):
@login_required @login_required
def create(request): def create(request):
tenants = api.tenant_list(request) try:
tenants = api.tenant_list(request)
except api_exceptions.ApiException, e:
messages.error(request, 'Unable to retrieve tenant list: %s' %
e.message)
return redirect('syspanel_users')
if request.method == "POST": if request.method == "POST":
form = UserForm(request.POST, tenant_list=tenants) form = UserForm(request.POST, tenant_list=tenants)
@@ -133,6 +143,9 @@ def create(request):
user['password'], user['password'],
user['tenant_id'], user['tenant_id'],
True) True)
api.account_api(request).role_refs.add_for_tenant_user(
user['tenant_id'], user['id'],
settings.OPENSTACK_KEYSTONE_DEFAULT_ROLE)
messages.success(request, messages.success(request,
'%s was successfully created.' '%s was successfully created.'

View File

@@ -1,8 +1,9 @@
<form id="form_add_tenant_user{{user.id}}" method="post"> <form id="form_add_tenant_user{{user}}" method="post">
{% csrf_token %} {% csrf_token %}
{% for hidden in form.hidden_fields %} {% for hidden in form.hidden_fields %}
{{hidden}} {{hidden}}
{% endfor %} {% endfor %}
<input name="user" type="hidden" value="{{user.id}}" /> <input name="user" type="hidden" value="{{user}}" />
<input id="add_tenant_user_{{user.id}}" class="add" ttle="User: {{user.id}}" type="submit" value="Delete" /> <input name="tenant" type="hidden" value="{{tenant_id}}" />
<input id="add_tenant_user_{{user}}" class="add" ttle="User: {{user}}" type="submit" value="Add" />
</form> </form>

View File

@@ -0,0 +1,10 @@
<form id="tenant_form" method="post">
{% csrf_token %}
{% for hidden in form.hidden_fields %}{{ hidden }}{% endfor %}
{% for field in form.visible_fields %}
{{ field.label_tag }}
{{ field.errors }}
{{ field }}
{% endfor %}
<input type="submit" value="Update Instance" class="large-rounded" />
</form>

View File

@@ -40,6 +40,7 @@
<li>{% include "_reboot.html" with form=reboot_form %}</li> <li>{% include "_reboot.html" with form=reboot_form %}</li>
<li><a target="_blank" href="{% url dash_instances_console request.user.tenant instance.id %}">Log</a></li> <li><a target="_blank" href="{% url dash_instances_console request.user.tenant instance.id %}">Log</a></li>
<li><a target="_blank" href="{% url dash_instances_vnc request.user.tenant instance.id %}">VNC Console</a></li> <li><a target="_blank" href="{% url dash_instances_vnc request.user.tenant instance.id %}">VNC Console</a></li>
<li><a href="{% url dash_instances_update request.user.tenant instance.id %}">Edit</a></li>
</ul> </ul>
</td> </td>
</tr> </tr>

View File

@@ -0,0 +1,36 @@
{% extends 'dash_base.html' %}
{% block sidebar %}
{% with current_sidebar="instances" %}
{{block.super}}
{% endwith %}
{% endblock %}
{% block main %}
<div id='page_header'>
<h2><span>Compute:</span> Update Instance </h2>
<!--
<p class='desc'><span>&mdash;</span>Update Instance</p>
-->
</div>
{% include "_messages.html" %}
<div class="main_content">
<div class="dash_block wide form">
<div class='title_block'>
<h3>Update Instance</h3>
</div>
<div class="left">
{% include '_instance_form.html' with form=form %}
<h3><a href="{% url dash_instances request.user.tenant %}"><< Return to Instances List</a></h3>
</div>
<div class="right">
<h3>Description:</h3>
<p>Update the name and description of your instance</p>
</div>
</div>
</div>
{% endblock %}

View File

@@ -39,7 +39,7 @@
<div class="usage_block"> <div class="usage_block">
<h3>RAM</h3> <h3>RAM</h3>
<ul> <ul>
<li><span class="quantity">{{usage.total_active_ram_size}}</span><span class="unit">GB</span> Active</li> <li><span class="quantity">{{usage.total_active_ram_size}}</span><span class="unit">MB</span> Active</li>
</ul> </ul>
</div> </div>

View File

@@ -57,5 +57,26 @@
<p>There are currently no users for this tenant</p> <p>There are currently no users for this tenant</p>
</div> </div>
{% endif %} {% endif %}
{% if new_users %}
<h3>Add new users</h3>
<table class="wide">
<tr id='headings'>
<th>Name</th>
<th>Actions</th>
</tr>
<tbody class='main'>
{% for user in new_users %}
<tr class="{% cycle 'odd' 'even' %}">
<td>{{user}}</td>
<td id="actions">
<ul>
<li>{% include "_add_tenant_user.html" with form=add_user_form %}</li>
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</div> </div>
{% endblock %} {% endblock %}

View File

@@ -23,6 +23,7 @@ CACHE_BACKEND = 'dummy://'
OPENSTACK_ADMIN_TOKEN = "999888777666" OPENSTACK_ADMIN_TOKEN = "999888777666"
OPENSTACK_KEYSTONE_URL = "http://localhost:8080/v2.0/" OPENSTACK_KEYSTONE_URL = "http://localhost:8080/v2.0/"
OPENSTACK_KEYSTONE_DEFAULT_ROLE = "Member"
# If you have external monitoring links # If you have external monitoring links
EXTERNAL_MONITORING = [ EXTERNAL_MONITORING = [