add flavors support
This commit is contained in:
@@ -19,6 +19,11 @@ urlpatterns += patterns('django_openstack.syspanel.views.images',
|
||||
#url(INSTANCES % 'vnc', 'vnc', name='syspanel_instances_vnc'),
|
||||
)
|
||||
|
||||
urlpatterns += patterns('django_openstack.syspanel.views.flavors',
|
||||
url(r'^flavors/$', 'index', name='syspanel_flavors'),
|
||||
url(r'^flavors/create/$', 'create', name='syspanel_flavors_create'),
|
||||
)
|
||||
|
||||
|
||||
urlpatterns_OLD = patterns('',
|
||||
url(r'^$', 'django_openstack.syspanel.views.home.index', name='syspanel_index'),
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
from django import template
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.shortcuts import render_to_response
|
||||
|
||||
|
||||
@login_required
|
||||
def index(request):
|
||||
nova = get_nova_admin_connection()
|
||||
nodes = nova.get_hosts()
|
||||
return render_to_response('django_nova_syspanel/cloudview/index.html',
|
||||
{'nodes': nodes, },
|
||||
context_instance=template.RequestContext(request))
|
||||
@@ -0,0 +1,78 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
from operator import itemgetter
|
||||
|
||||
from django import template
|
||||
from django import http
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.shortcuts import redirect
|
||||
from django.shortcuts import render_to_response
|
||||
import openstackx.compute.exceptions as api_exceptions
|
||||
|
||||
|
||||
from django_openstack import api
|
||||
from django_openstack import forms
|
||||
|
||||
|
||||
class CreateFlavor(forms.SelfHandlingForm):
|
||||
flavorid = forms.CharField(max_length="10", label="Flavor ID")
|
||||
name = forms.CharField(max_length="5", label="Name")
|
||||
vcpus = forms.CharField(max_length="5", label="VCPUs")
|
||||
memory_mb = forms.CharField(max_length="5", label="Memory MB")
|
||||
disk_gb = forms.CharField(max_length="5", label="Disk GB")
|
||||
|
||||
def handle(self, request, data):
|
||||
api.admin_api(request).flavors.create(data['name'],
|
||||
int(data['memory_mb']),
|
||||
int(data['vcpus']),
|
||||
int(data['disk_gb']),
|
||||
int(data['flavorid']))
|
||||
messages.success(request,
|
||||
'%s was successfully added to flavors.' % data['name'])
|
||||
return redirect('syspanel_flavors')
|
||||
|
||||
|
||||
class DeleteFlavor(forms.SelfHandlingForm):
|
||||
flavorid = forms.CharField(required=True)
|
||||
|
||||
def handle(self, request, data):
|
||||
flavor_id = data['flavorid']
|
||||
api.admin_api(request).flavors.delete(flavor_id, True)
|
||||
return redirect(request.build_absolute_uri())
|
||||
|
||||
|
||||
@login_required
|
||||
def index(request):
|
||||
for f in (DeleteFlavor,):
|
||||
_, handled = f.maybe_handle(request)
|
||||
if handled:
|
||||
return handled
|
||||
|
||||
# We don't have any way of showing errors for these, so don't bother
|
||||
# trying to reuse the forms from above
|
||||
delete_form = DeleteFlavor()
|
||||
|
||||
flavors = []
|
||||
try:
|
||||
flavors = api.admin_api(request).flavors.list()
|
||||
except api_exceptions.ApiException, e:
|
||||
messages.error(request, 'Unable to get usage info: %s' % e.message)
|
||||
|
||||
flavors.sort(key=lambda x: x.id, reverse=True)
|
||||
return render_to_response('syspanel_flavors.html',{
|
||||
'delete_form': delete_form,
|
||||
'flavors': flavors,
|
||||
}, context_instance = template.RequestContext(request))
|
||||
|
||||
|
||||
@login_required
|
||||
def create(request):
|
||||
form, handled = CreateFlavor.maybe_handle(request)
|
||||
if handled:
|
||||
return handled
|
||||
|
||||
return render_to_response('syspanel_create_flavor.html',{
|
||||
'form': form,
|
||||
}, context_instance = template.RequestContext(request))
|
||||
@@ -1,10 +0,0 @@
|
||||
from django import template
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.shortcuts import render_to_response
|
||||
|
||||
|
||||
@login_required
|
||||
def index(request):
|
||||
return render_to_response('django_nova_syspanel/index.html',
|
||||
{},
|
||||
context_instance=template.RequestContext(request))
|
||||
@@ -1,61 +0,0 @@
|
||||
from boto.exception import EC2ResponseError
|
||||
from django import template
|
||||
from django.conf import settings
|
||||
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 _
|
||||
|
||||
|
||||
@login_required
|
||||
def index(request):
|
||||
nova = get_nova_admin_connection()
|
||||
conn = nova.connection_for(settings.NOVA_ADMIN_USER, settings.NOVA_PROJECT)
|
||||
volumes = conn.get_all_volumes()
|
||||
|
||||
for volume in volumes:
|
||||
statusstr = str(volume.status)[:-1]
|
||||
instance = statusstr.split(', ')[-2]
|
||||
device = statusstr.split(', ')[-1]
|
||||
status = statusstr.split(' ')[0]
|
||||
|
||||
volume.device = device
|
||||
volume.instance = instance
|
||||
volume.status_str = status
|
||||
|
||||
return render_to_response('django_nova_syspanel/volumes/index.html',
|
||||
{'volumes': volumes, },
|
||||
context_instance=template.RequestContext(request))
|
||||
|
||||
|
||||
@login_required
|
||||
def detach(request, volume_id):
|
||||
nova = get_nova_admin_connection()
|
||||
conn = nova.connection_for(settings.NOVA_ADMIN_USER, settings.NOVA_PROJECT)
|
||||
try:
|
||||
conn.detach_volume(volume_id)
|
||||
except EC2ResponseError, e:
|
||||
messages.error(request, 'Unable to detach volume %s: %s' % \
|
||||
(volume_id, e.error_message))
|
||||
else:
|
||||
messages.success(request,
|
||||
_('Volume %s has been scheduled to be detached.') %
|
||||
volume_id)
|
||||
return redirect('syspanel_volumes')
|
||||
|
||||
|
||||
@login_required
|
||||
def delete(request, volume_id):
|
||||
nova = get_nova_admin_connection()
|
||||
conn = nova.connection_for(settings.NOVA_ADMIN_USER, settings.NOVA_PROJECT)
|
||||
try:
|
||||
conn.delete_volume(volume_id)
|
||||
except EC2ResponseError, e:
|
||||
messages.error(request,
|
||||
_('Unable to delete volume %(vol)s: %(msg)s') %
|
||||
{'vol': volume_id, 'msg': e.error_message})
|
||||
else:
|
||||
messages.success(request,
|
||||
_('Volume %s has been successfully deleted.') %
|
||||
volume_id)
|
||||
return redirect('syspanel_volumes')
|
||||
@@ -1,59 +0,0 @@
|
||||
from django import http
|
||||
from django import template
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.shortcuts import redirect, render_to_response
|
||||
|
||||
|
||||
@login_required
|
||||
def index(request):
|
||||
nova = get_nova_admin_connection()
|
||||
vpns = nova.get_vpns()
|
||||
return render_to_response('django_nova_syspanel/vpns/index.html',
|
||||
{'vpns': vpns, },
|
||||
context_instance=template.RequestContext(request))
|
||||
|
||||
|
||||
@login_required
|
||||
def console(request, project_id):
|
||||
nova = get_nova_admin_connection()
|
||||
conn = nova.connection_for(settings.NOVA_ADMIN_USER, project_id)
|
||||
vpn = [x for x in nova.get_vpns() if x.project_id == project_id][0]
|
||||
console = conn.get_console_output(vpn.instance_id)
|
||||
response = http.HttpResponse(mimetype='text/plain')
|
||||
response.write(console.output)
|
||||
response.flush()
|
||||
return response
|
||||
|
||||
|
||||
@login_required
|
||||
def restart(request, project_id):
|
||||
nova = get_nova_admin_connection()
|
||||
conn = nova.connection_for(settings.NOVA_ADMIN_USER, project_id)
|
||||
vpn = [x for x in nova.get_vpns() if x.project_id == project_id][0]
|
||||
conn.reboot_instances([vpn.instance_id])
|
||||
return redirect('django_nova_syspanel/vpns')
|
||||
|
||||
|
||||
@login_required
|
||||
def terminate(request, project_id):
|
||||
nova = get_nova_admin_connection()
|
||||
conn = nova.connection_for(settings.NOVA_ADMIN_USER, project_id)
|
||||
vpn = [x for x in nova.get_vpns() if x.project_id == project_id][0]
|
||||
conn.terminate_instances([vpn.instance_id])
|
||||
return redirect('django_nova_syspanel/vpns')
|
||||
|
||||
|
||||
@login_required
|
||||
def launch(request, project_id):
|
||||
nova = get_nova_admin_connection()
|
||||
nova.start_vpn(project_id)
|
||||
return redirect('django_nova_syspanel/vpns')
|
||||
|
||||
|
||||
@login_required
|
||||
def send_credentials(request, project_id, user_id):
|
||||
# TODO we need to pass a user id as well
|
||||
nova = get_nova_admin_connection()
|
||||
nova.get_zip(user_id, project_id)
|
||||
return redirect('django_nova_syspanel/vpns')
|
||||
@@ -0,0 +1,5 @@
|
||||
{% extends 'django_openstack/syspanel/_create_flavor.html' %}
|
||||
|
||||
{% block submit %}
|
||||
<input type="submit" value="Create Flavor" class="large-rounded" />
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,8 @@
|
||||
<form id="form_delete_{{flavor.id}}" class="form-delete" method="post">
|
||||
{% csrf_token %}
|
||||
{% for hidden in form.hidden_fields %}
|
||||
{{hidden}}
|
||||
{% endfor %}
|
||||
<input name="flavorid" type="hidden" value="{{flavor.id}}" />
|
||||
<input id="delete_{{flavor.id}}" class="delete" type="submit" value="Delete" />
|
||||
</form>
|
||||
@@ -0,0 +1,24 @@
|
||||
<table class="wide">
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Name</th>
|
||||
<th>VCPUs</th>
|
||||
<th>Memory</th>
|
||||
<th>Disk</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
{% for flavor in flavors %}
|
||||
<tr id="{{flavor.id}}" class="{% cycle 'odd' 'even' %}">
|
||||
<td>{{flavor.id}}</td>
|
||||
<td>{{flavor.name}}</td>
|
||||
<td>{{flavor.vcpus}}</td>
|
||||
<td>{{flavor.ram}}</td>
|
||||
<td>{{flavor.disk}}</td>
|
||||
<td id="actions">
|
||||
<ul>
|
||||
<li>{% include "_delete_flavor.html" with form=delete_form %}</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
@@ -4,5 +4,6 @@
|
||||
<li><a {% if current_sidebar == "overview" %} class="active" {% endif %} href="{% url syspanel_overview %}">Overview</a></li>
|
||||
<li><a {% if current_sidebar == "instances" %} class="active" {% endif %} href="{% url syspanel_instances %}">Instances</a></li>
|
||||
<li><a {% if current_sidebar == "images" %} class="active" {% endif %} href="{% url syspanel_images %}">Images</a></li>
|
||||
<li><a {% if current_sidebar == "flavors" %} class="active" {% endif %} href="{% url syspanel_flavors %}">Flavors</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
{% extends 'syspanel_base.html' %}
|
||||
{# list of user's instances #}
|
||||
{# standard nav, sidebar, list of instances in main #}
|
||||
|
||||
{% block sidebar %}
|
||||
{% with current_sidebar="flavors" %}
|
||||
{{block.super}}
|
||||
{% endwith %}
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div id='page_header'>
|
||||
<h2><span>System Panel:</span> Flavors</h2>
|
||||
<p class='desc'><span>—</span> Create, Edit and Delete Flavors.</p>
|
||||
</div>
|
||||
`
|
||||
{% include "_messages.html" %}
|
||||
|
||||
<div class="main_content">
|
||||
<div class="dash_block wide form">
|
||||
<div class='title_block'>
|
||||
<h3>Create Flavor</h3>
|
||||
</div>
|
||||
|
||||
{% include "_create_flavor.html" %}
|
||||
|
||||
<div class="right">
|
||||
<h3>Description:</h3>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus vitae est urna. Phasellus sagittis, sem posuere hendrerit mattis, velit risus viverra enim, tempus dapibus sem turpis ac erat.</p>
|
||||
<p>Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed mollis ligula nec lacus mollis eu laoreet lectus porta. </p>
|
||||
<p>Sed iaculis mauris et est consectetur egestas. Praesent dolor libero, semper sed aliquet</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,37 @@
|
||||
{% extends 'syspanel_base.html' %}
|
||||
{# list of user's instances #}
|
||||
{# standard nav, sidebar, list of instances in main #}
|
||||
|
||||
{% block sidebar %}
|
||||
{% with current_sidebar="flavors" %}
|
||||
{{block.super}}
|
||||
{% endwith %}
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div id='page_header'>
|
||||
<h2><span>System Panel:</span> Flavors</h2>
|
||||
<p class='desc'><span>—</span> Create, Edit and Delete Flavors.</p>
|
||||
</div>
|
||||
`
|
||||
{% include "_messages.html" %}
|
||||
<div class="main_content">
|
||||
<div class='table_title wide'>
|
||||
<h3>Flavors</h3>
|
||||
<a class="refresh" href="{% url syspanel_flavors %}">Refresh List</a>
|
||||
<div class='search'>
|
||||
<form action='' method='post'>
|
||||
<fieldset>
|
||||
<label for='table_search'>Search</label>
|
||||
<input id='table_search' name='search' type='text' value='' />
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include "_syspanel_flavor_list.html" %}
|
||||
|
||||
<a id="flavor_create_link" href="{% url syspanel_flavors_create %}">Create New Flavor >></a>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user