Merge pull request #143 from cloudbuilders/keypair-import
Keypair import
This commit is contained in:
@@ -502,6 +502,10 @@ def keypair_create(request, name):
|
||||
return KeyPair(novaclient(request).keypairs.create(name))
|
||||
|
||||
|
||||
def keypair_import(request, name, public_key):
|
||||
return KeyPair(novaclient(request).keypairs.create(name, public_key))
|
||||
|
||||
|
||||
def keypair_delete(request, keypair_id):
|
||||
novaclient(request).keypairs.delete(keypair_id)
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ urlpatterns += patterns('django_openstack.dash.views.images',
|
||||
urlpatterns += patterns('django_openstack.dash.views.keypairs',
|
||||
url(r'^(?P<tenant_id>[^/]+)/keypairs/$', 'index', name='dash_keypairs'),
|
||||
url(KEYPAIRS % 'create', 'create', name='dash_keypairs_create'),
|
||||
url(KEYPAIRS % 'import', 'import_keypair', name='dash_keypairs_import'),
|
||||
)
|
||||
|
||||
urlpatterns += patterns('django_openstack.dash.views.floating_ips',
|
||||
|
||||
@@ -28,7 +28,7 @@ from django import template
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core import validators
|
||||
from django import shortcuts
|
||||
from django.shortcuts import redirect, render_to_response
|
||||
|
||||
from django_openstack import api
|
||||
from django_openstack import forms
|
||||
@@ -50,7 +50,7 @@ class DeleteKeypair(forms.SelfHandlingForm):
|
||||
except novaclient_exceptions.ClientException, e:
|
||||
LOG.exception("ClientException in DeleteKeypair")
|
||||
messages.error(request, 'Error deleting keypair: %s' % e.message)
|
||||
return shortcuts.redirect(request.build_absolute_uri())
|
||||
return redirect(request.build_absolute_uri())
|
||||
|
||||
|
||||
class CreateKeypair(forms.SelfHandlingForm):
|
||||
@@ -70,7 +70,26 @@ class CreateKeypair(forms.SelfHandlingForm):
|
||||
except novaclient_exceptions.ClientException, e:
|
||||
LOG.exception("ClientException in CreateKeyPair")
|
||||
messages.error(request, 'Error Creating Keypair: %s' % e.message)
|
||||
return shortcuts.redirect(request.build_absolute_uri())
|
||||
return redirect(request.build_absolute_uri())
|
||||
|
||||
|
||||
class ImportKeypair(forms.SelfHandlingForm):
|
||||
|
||||
name = forms.CharField(max_length="20", label="Keypair Name",
|
||||
validators=[validators.RegexValidator('\w+')])
|
||||
public_key = forms.CharField(label='Public Key', widget=forms.Textarea)
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
LOG.info('Importing keypair "%s"' % data['name'])
|
||||
api.keypair_import(request, data['name'], data['public_key'])
|
||||
messages.success(request, 'Successfully imported public key: %s'
|
||||
% data['name'])
|
||||
return redirect('dash_keypairs', request.user.tenant_id)
|
||||
except novaclient_exceptions.ClientException, e:
|
||||
LOG.exception("ClientException in ImportKeypair")
|
||||
messages.error(request, 'Error Importing Keypair: %s' % e.message)
|
||||
return redirect(request.build_absolute_uri())
|
||||
|
||||
|
||||
@login_required
|
||||
@@ -87,8 +106,7 @@ def index(request, tenant_id):
|
||||
LOG.exception("ClientException in keypair index")
|
||||
messages.error(request, 'Error fetching keypairs: %s' % e.message)
|
||||
|
||||
return shortcuts.render_to_response(
|
||||
'django_openstack/dash/keypairs/index.html', {
|
||||
return render_to_response('django_openstack/dash/keypairs/index.html', {
|
||||
'keypairs': keypairs,
|
||||
'delete_form': delete_form,
|
||||
}, context_instance=template.RequestContext(request))
|
||||
@@ -100,7 +118,17 @@ def create(request, tenant_id):
|
||||
if handled:
|
||||
return handled
|
||||
|
||||
return shortcuts.render_to_response(
|
||||
'django_openstack/dash/keypairs/create.html', {
|
||||
return render_to_response('django_openstack/dash/keypairs/create.html', {
|
||||
'create_form': form,
|
||||
}, context_instance=template.RequestContext(request))
|
||||
|
||||
|
||||
@login_required
|
||||
def import_keypair(request, tenant_id):
|
||||
form, handled = ImportKeypair.maybe_handle(request)
|
||||
if handled:
|
||||
return handled
|
||||
|
||||
return render_to_response('django_openstack/dash/keypairs/import.html', {
|
||||
'create_form': form,
|
||||
}, context_instance=template.RequestContext(request))
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
{{ field.errors }}
|
||||
{{ field }}
|
||||
{% endfor %}
|
||||
<input type="submit" value="Create Keypair" class="large-rounded" />
|
||||
<input type="submit" value="Add Keypair" class="large-rounded" />
|
||||
</form>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
{% extends 'django_openstack/dash/base.html' %}
|
||||
|
||||
{% block sidebar %}
|
||||
{% with current_sidebar="keypairs" %}
|
||||
{{block.super}}
|
||||
{% endwith %}
|
||||
{% endblock %}
|
||||
|
||||
{% block headerjs %}
|
||||
{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{# to make searchable false, just remove it from the include statement #}
|
||||
{% include "django_openstack/common/_page_header.html" with title="Create Keypair" %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block dash_main %}
|
||||
<div class="dash_block">
|
||||
<div class="left">
|
||||
{% include 'django_openstack/dash/keypairs/_form.html' with form=create_form %}
|
||||
<h3><a href="{% url dash_keypairs request.user.tenant_id %}"><< Return to keypairs list</a></h3>
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
<h3>Description:</h3>
|
||||
<p>Keypairs are ssh credentials which are injected into images when they are launched. Creating a new key pair registers the public key and downloads the private key (a .pem file).</p>
|
||||
<p>Protect and use the key as you would any normal ssh private key.</p>
|
||||
</div>
|
||||
<div class="clear"> </div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -15,11 +15,14 @@
|
||||
{% block dash_main %}
|
||||
{% if keypairs %}
|
||||
{% include 'django_openstack/dash/keypairs/_list.html' %}
|
||||
<a id="keypairs_create_link" class="action_link large-rounded" href="{% url dash_keypairs_create request.user.tenant_id %}">Create New Keypair</a>
|
||||
<a id="keypairs_create_link" class="action_link large-rounded" href="{% url dash_keypairs_create request.user.tenant_id %}">Add New Keypair</a>
|
||||
<a id="keypairs_import_link" class="action_link large-rounded" href="{% url dash_keypairs_import request.user.tenant_id %}">Import Keypair</a>
|
||||
{% else %}
|
||||
<div class="message_box info">
|
||||
<h2>Info</h2>
|
||||
<p>There are currently no keypairs. <a href='{% url dash_keypairs_create request.user.tenant_id %}'>Create A Keypair >></a></p>
|
||||
<p>There are currently no keypairs.</p>
|
||||
</div>
|
||||
<a id="keypairs_create_link" class="action_link large-rounded" href="{% url dash_keypairs_create request.user.tenant_id %}">Add New Keypair</a>
|
||||
<a id="keypairs_import_link" class="action_link large-rounded" href="{% url dash_keypairs_import request.user.tenant_id %}">Import Keypair</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -309,13 +309,13 @@ class ApiHelperTests(test.TestCase):
|
||||
GLANCE_URL = 'http://glance/glanceapi/'
|
||||
NOVA_URL = 'http://nova/novapi/'
|
||||
|
||||
url = api.url_for(self.request, 'image')
|
||||
url = api.url_for(self.request, 'glance')
|
||||
self.assertEqual(url, GLANCE_URL + 'internal')
|
||||
|
||||
url = api.url_for(self.request, 'image', admin=False)
|
||||
url = api.url_for(self.request, 'glance', admin=False)
|
||||
self.assertEqual(url, GLANCE_URL + 'internal')
|
||||
|
||||
url = api.url_for(self.request, 'image', admin=True)
|
||||
url = api.url_for(self.request, 'glance', admin=True)
|
||||
self.assertEqual(url, GLANCE_URL + 'admin')
|
||||
|
||||
url = api.url_for(self.request, 'compute')
|
||||
@@ -1177,6 +1177,19 @@ class APIExtensionTests(NovaClientTestMixin, test.TestCase):
|
||||
|
||||
self.mox.VerifyAll()
|
||||
|
||||
def test_keypair_import(self):
|
||||
novaclient = self.stub_novaclient()
|
||||
|
||||
novaclient.keypairs = self.mox.CreateMockAnything()
|
||||
novaclient.keypairs.create(IsA(str), IsA(str)).AndReturn(self.keypair)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.keypair_import(self.request, TEST_RETURN, TEST_RETURN)
|
||||
self.assertIsInstance(ret_val, api.KeyPair)
|
||||
self.assertEqual(ret_val.name, self.keypair.name)
|
||||
|
||||
self.mox.VerifyAll()
|
||||
|
||||
def test_keypair_delete(self):
|
||||
novaclient = self.stub_novaclient()
|
||||
|
||||
@@ -1225,7 +1238,7 @@ class GlanceApiTests(test.TestCase):
|
||||
client_instance.auth_tok = TEST_TOKEN
|
||||
|
||||
self.mox.StubOutWithMock(api, 'url_for')
|
||||
api.url_for(IsA(http.HttpRequest), 'image').AndReturn(TEST_URL)
|
||||
api.url_for(IsA(http.HttpRequest), 'glance').AndReturn(TEST_URL)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user