Skip to content

Commit

Permalink
Fixing some pep8 issues with volumes.
Browse files Browse the repository at this point in the history
Change-Id: I908c7457e47ba7da3d3df37679298ed98ce097b0
  • Loading branch information
treshenry committed Nov 2, 2011
1 parent 0ea6068 commit d3d71ff
Show file tree
Hide file tree
Showing 16 changed files with 604 additions and 21 deletions.
41 changes: 39 additions & 2 deletions django-openstack/django_openstack/api.py
Expand Up @@ -166,6 +166,12 @@ class KeyPair(APIResourceWrapper):
_attrs = ['fingerprint', 'name', 'private_key']


class Volume(APIResourceWrapper):
"""Nova Volume representation"""
_attrs = ['id', 'status', 'displayName', 'size', 'volumeType', 'createdAt',
'attachments', 'displayDescription']


class Server(APIResourceWrapper):
"""Simple wrapper around openstackx.extras.server.Server
Expand Down Expand Up @@ -555,6 +561,37 @@ def keypair_list(request):
return [KeyPair(key) for key in novaclient(request).keypairs.list()]


def volume_list(request):
return [Volume(vol) for vol in novaclient(request).volumes.list()]


def volume_get(request, volume_id):
return Volume(novaclient(request).volumes.get(volume_id))


def volume_instance_list(request, instance_id):
return novaclient(request).volumes.get_server_volumes(instance_id)


def volume_create(request, size, name, description):
return Volume(novaclient(request).volumes.create(
size, name, description))


def volume_delete(request, volume_id):
novaclient(request).volumes.delete(volume_id)


def volume_attach(request, volume_id, instance_id, device):
novaclient(request).volumes.create_server_volume(
instance_id, volume_id, device)


def volume_detach(request, instance_id, attachment_id):
novaclient(request).volumes.delete_server_volume(
instance_id, attachment_id)


def server_create(request, name, image, flavor,
key_name, user_data, security_groups):
return Server(novaclient(request).servers.create(
Expand Down Expand Up @@ -991,8 +1028,8 @@ def service(self):
self.service_list = service_list(self.request)
except api_exceptions.ApiException, e:
self.service_list = []
LOG.exception('ApiException fetching service list '
'in instance usage')
LOG.exception('ApiException fetching service list in instance '
'usage')
messages.error(self.request,
_('Unable to get service info: %s') % e.message)
return
Expand Down
13 changes: 11 additions & 2 deletions django-openstack/django_openstack/dash/urls.py
Expand Up @@ -20,12 +20,13 @@

from django.conf.urls.defaults import *

SECURITY_GROUPS = r('^(?P<tenant_id>[^/]+)/security_groups/'
'(?P<security_group_id>[^/]+)/%s$')
SECURITY_GROUPS = r'^(?P<tenant_id>[^/]+)/security_groups/' \
'(?P<security_group_id>[^/]+)/%s$'
INSTANCES = r'^(?P<tenant_id>[^/]+)/instances/(?P<instance_id>[^/]+)/%s$'
IMAGES = r'^(?P<tenant_id>[^/]+)/images/(?P<image_id>[^/]+)/%s$'
KEYPAIRS = r'^(?P<tenant_id>[^/]+)/keypairs/%s$'
SNAPSHOTS = r'^(?P<tenant_id>[^/]+)/snapshots/(?P<instance_id>[^/]+)/%s$'
VOLUMES = r'^(?P<tenant_id>[^/]+)/volumes/(?P<volume_id>[^/]+)/%s$'
CONTAINERS = r'^(?P<tenant_id>[^/]+)/containers/%s$'
FLOATING_IPS = r'^(?P<tenant_id>[^/]+)/floating_ips/(?P<ip_id>[^/]+)/%s$'
OBJECTS = r'^(?P<tenant_id>[^/]+)/containers/(?P<container_name>[^/]+)/%s$'
Expand Down Expand Up @@ -78,6 +79,14 @@
url(SNAPSHOTS % 'create', 'create', name='dash_snapshots_create'),
)

urlpatterns += patterns('django_openstack.dash.views.volumes',
url(r'^(?P<tenant_id>[^/]+)/volumes/$', 'index', name='dash_volumes'),
url(r'^(?P<tenant_id>[^/]+)/volumes/create', 'create',
name='dash_volumes_create'),
url(VOLUMES % 'attach', 'attach', name='dash_volumes_attach'),
url(VOLUMES % 'detail', 'detail', name='dash_volumes_detail'),
)

# Swift containers and objects.
urlpatterns += patterns('django_openstack.dash.views.containers',
url(CONTAINERS % '', 'index', name='dash_containers'),
Expand Down
2 changes: 2 additions & 0 deletions django-openstack/django_openstack/dash/views/instances.py
Expand Up @@ -293,6 +293,7 @@ def update(request, tenant_id, instance_id):
def detail(request, tenant_id, instance_id):
try:
instance = api.server_get(request, instance_id)
volumes = api.volume_instance_list(request, instance_id)
try:
console = api.console_create(request, instance_id, 'vnc')
vnc_url = "%s&title=%s(%s)" % (console.output,
Expand All @@ -316,4 +317,5 @@ def detail(request, tenant_id, instance_id):
'django_openstack/dash/instances/detail.html', {
'instance': instance,
'vnc_url': vnc_url,
'volumes': volumes
}, context_instance=template.RequestContext(request))
182 changes: 182 additions & 0 deletions django-openstack/django_openstack/dash/views/volumes.py
@@ -0,0 +1,182 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2011 Nebula, Inc.
# All rights reserved.

"""
Views for managing Nova volumes.
"""

import logging

from django import template
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect, render_to_response
from django.utils.translation import ugettext as _

from django_openstack import api
from django_openstack import forms
from novaclient import exceptions as novaclient_exceptions


LOG = logging.getLogger('django_openstack.dash.views.volumes')


class CreateForm(forms.SelfHandlingForm):
name = forms.CharField(max_length="255", label="Volume Name")
description = forms.CharField(widget=forms.Textarea,
label=_("Description"), required=False)
size = forms.IntegerField(min_value=1, label="Size (GB)")

def handle(self, request, data):
try:
api.volume_create(request, data['size'], data['name'],
data['description'])
message = 'Creating volume "%s"' % data['name']
LOG.info(message)
messages.info(request, message)
except novaclient_exceptions.ClientException, e:
LOG.exception("ClientException in CreateVolume")
messages.error(request,
_('Error Creating Volume: %s') % e.message)
return redirect(request.build_absolute_uri())


class DeleteForm(forms.SelfHandlingForm):
volume_id = forms.CharField(widget=forms.HiddenInput())
volume_name = forms.CharField(widget=forms.HiddenInput())

def handle(self, request, data):
try:
api.volume_delete(request, data['volume_id'])
message = 'Deleting volume "%s"' % data['volume_id']
LOG.info(message)
messages.info(request, message)
except novaclient_exceptions.ClientException, e:
LOG.exception("ClientException in DeleteVolume")
messages.error(request,
_('Error deleting volume: %s') % e.message)
return redirect(request.build_absolute_uri())


class AttachForm(forms.SelfHandlingForm):
volume_id = forms.CharField(widget=forms.HiddenInput())
device = forms.CharField(label="Device Name", initial="/dev/vdb")

def __init__(self, *args, **kwargs):
super(AttachForm, self).__init__(*args, **kwargs)
instance_list = kwargs.get('initial', {}).get('instance_list', [])
self.fields['instance'] = forms.ChoiceField(
choices=instance_list,
label="Attach to Instance",
help_text="Select an instance to attach to.")

def handle(self, request, data):
try:
api.volume_attach(request, data['volume_id'], data['instance'],
data['device'])
message = (_('Attaching volume %s to instance %s at %s') %
(data['volume_id'], data['instance'],
data['device']))
LOG.info(message)
messages.info(request, message)
except novaclient_exceptions.ClientException, e:
LOG.exception("ClientException in AttachVolume")
messages.error(request,
_('Error attaching volume: %s') % e.message)
return redirect(request.build_absolute_uri())


class DetachForm(forms.SelfHandlingForm):
volume_id = forms.CharField(widget=forms.HiddenInput())
instance_id = forms.CharField(widget=forms.HiddenInput())
attachment_id = forms.CharField(widget=forms.HiddenInput())

def handle(self, request, data):
try:
api.volume_detach(request, data['instance_id'],
data['attachment_id'])
message = (_('Detaching volume %s from instance %s') %
(data['volume_id'], data['instance_id']))
LOG.info(message)
messages.info(request, message)
except novaclient_exceptions.ClientException, e:
LOG.exception("ClientException in DetachVolume")
messages.error(request,
_('Error detaching volume: %s') % e.message)
return redirect(request.build_absolute_uri())


@login_required
def index(request, tenant_id):
delete_form, handled = DeleteForm.maybe_handle(request)
detach_form, handled = DetachForm.maybe_handle(request)

if handled:
return handled

try:
volumes = api.volume_list(request)
except novaclient_exceptions.ClientException, e:
volumes = []
LOG.exception("ClientException in volume index")
messages.error(request, _('Error fetching volumes: %s') % e.message)

return render_to_response('django_openstack/dash/volumes/index.html', {
'volumes': volumes, 'delete_form': delete_form,
'detach_form': detach_form
}, context_instance=template.RequestContext(request))


@login_required
def detail(request, tenant_id, volume_id):
try:
volume = api.volume_get(request, volume_id)
attachment = volume.attachments[0]
if attachment:
instance = api.server_get(
request, volume.attachments[0]['serverId'])
else:
instance = None
except novaclient_exceptions.ClientException, e:
LOG.exception("ClientException in volume get")
messages.error(request, _('Error fetching volume: %s') % e.message)
return redirect('dash_volumes', tenant_id)

return render_to_response('django_openstack/dash/volumes/detail.html', {
'volume': volume,
'attachment': attachment,
'instance': instance
}, context_instance=template.RequestContext(request))


@login_required
def create(request, tenant_id):
create_form, handled = CreateForm.maybe_handle(request)

if handled:
return handled

return render_to_response('django_openstack/dash/volumes/create.html', {
'create_form': create_form
}, context_instance=template.RequestContext(request))


@login_required
def attach(request, tenant_id, volume_id):

def instances():
insts = api.server_list(request)
return [(inst.id, '%s (Instance %s)' % (inst.name, inst.id))
for inst in insts]

attach_form, handled = AttachForm.maybe_handle(
request, initial={'instance_list': instances()})

if handled:
return handled

return render_to_response('django_openstack/dash/volumes/attach.html', {
'attach_form': attach_form, 'volume_id': volume_id
}, context_instance=template.RequestContext(request))
Expand Up @@ -11,6 +11,7 @@ <h3>{% trans "Manage Compute"%}</h3>
<li><a {% if current_sidebar == "keypairs" %} class="active" {% endif %} href="{% url dash_keypairs request.user.tenant_id %}">{% trans "Keypairs"%}</a></li>
<li><a {% if current_sidebar == "floatingips" %} class="active" {% endif %} href="{% url dash_floating_ips request.user.tenant_id %}">{% trans "Floating IPs"%}</a></li>
<li><a {% if current_sidebar == "security_groups" %} class="active" {% endif %} href="{% url dash_security_groups request.user.tenant_id %}">{% trans "Security Groups"%}</a></li>
<li><a {% if current_sidebar == "volumes" %} class="active" {% endif %} href="{% url dash_volumes request.user.tenant_id %}">{% trans "Volumes"%}</a></li>
{% if quantum_configured %}
<li><a {% if current_sidebar == "networks" %} class="active" {% endif %} href="{% url dash_networks request.user.tenant_id %}">{% trans "Networks"%}</a></li>
{% endif %}
Expand Down
@@ -1,4 +1,5 @@
{% extends 'django_openstack/dash/base.html' %}
{% load i18n %}

{% block sidebar %}
{% with current_sidebar="instances" %}
Expand All @@ -13,58 +14,77 @@

{% block dash_main %}
<ul id="instance_tabs">
<li class="active"><a class="overview" href="#">Overview</a></li>
<li><a class="log" href="#">Log</a></li>
<li><a class="vnc" href="#">VNC</a></li>
<li class="active"><a class="overview" href="#">{% trans "Overview" %}</a></li>
<li><a class="log" href="#">{% trans "Log" %}</a></li>
<li><a class="vnc" href="#">{% trans "VNC" %}</a></li>
</ul>

<div class="dash_block">
<div id="overview" class="tab_wrapper">
<ul>
<li>
<div class="status">
<h4>Status</h4>
<h4>{% trans "Status" %}</h4>
<ul>
<li><span>Status:</span> {{instance.status}}</li>
<li><span>Instance Name:</span> {{instance.name}}</li>
<li><span>Instance ID:</span> {{instance.id}}</li>
<li><span>{% trans "Status:" %}</span> {{instance.status}}</li>
<li><span>{% trans "Instance Name:" %}</span> {{instance.name}}</li>
<li><span>{% trans "Instance ID:" %}</span> {{instance.id}}</li>
</ul>
</div>
</li>

<li>
<div class="specs">
<h4>Specs</h4>
<h4>{% trans "Specs" %}</h4>
<ul>
<li><span>RAM:</span> {{instance.attrs.memory_mb}}</li>
<li><span>VCPUs:</span> {{instance.attrs.vcpus}} VCPU</li>
<li><span>Disk:</span> {{instance.attrs.disk_gb}}GB Disk</li>
<li><span>{% trans "RAM:" %}</span> {{instance.attrs.memory_mb}}</li>
<li><span>{% trans "VCPUs:" %}</span> {{instance.attrs.vcpus}} {% trans "VCPU" %}</li>
<li><span>{% trans "Disk:" %}</span> {{instance.attrs.disk_gb}}{% trans "GB Disk" %}</li>
</ul>
</div>
</li>

<li>
<div class="meta">
<h4>Meta</h4>
<h4>{% trans "Meta" %}</h4>
<ul>
<li><span>Key name:</span> {{instance.attrs.key_name}}</li>
<li><span>Security Group(s):</span> {% for group in instance.attrs.security_groups %}{{group}}, {% endfor %}</li>
<li><span>Image Name:</span> {{instance.image_name}}</li>
<li><span>{% trans "Key name:" %}</span> {{instance.attrs.key_name}}</li>
<li><span>{% trans "Security Group(s):" %}</span> {% for group in instance.attrs.security_groups %}{{group}}, {% endfor %}</li>
<li><span>{% trans "Image Name:" %}</span> {{instance.image_name}}</li>
</ul>
</div>
</li>
<li>
<div>
<h4>{% trans "Volumes" %}</h4>
<ul>
{% if volumes %}
{% for volume in volumes %}
<li>
<span>{% trans "Volume:" %}</span>
<a href="{% url dash_volumes_detail request.user.tenant_name volume.volumeId %}">
{{ volume.volumeId }} ({{ volume.device }})
</a>
</li>
{% endfor %}
{% else %}
<li><span>{% trans "None Attached" %}</span></li>
{% endif %}
</ul>
</div>
</li>
</ul>
</div>

<div id="log" class="tab_wrapper">
<a class="view_full" target="_blank" href="{% url dash_instances_console request.user.tenant_id instance.id %}">View Full Log</a>
<a class="view_full" target="_blank" href="{% url dash_instances_console request.user.tenant_id instance.id %}">{% trans "View Full Log" %}</a>
<pre class="logs"></pre>
</div>

<div id="vnc" class="tab_wrapper">
<iframe src="{{vnc_url}}" width="720" height="420"></iframe>
</div>

</div>
{% endblock %}

Expand Down

0 comments on commit d3d71ff

Please sign in to comment.