From d5bcc6764b418d7aa16b53b50173261385445ee8 Mon Sep 17 00:00:00 2001 From: Jesse Andrews Date: Tue, 9 Aug 2011 11:31:48 -0700 Subject: initial port --- nova/api/openstack/contrib/keypairs.py | 137 +++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 nova/api/openstack/contrib/keypairs.py (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/keypairs.py b/nova/api/openstack/contrib/keypairs.py new file mode 100644 index 000000000..879bd9712 --- /dev/null +++ b/nova/api/openstack/contrib/keypairs.py @@ -0,0 +1,137 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 OpenStack LLC. +# All Rights Reserved. +# +# 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. + +""" Keypair management extension""" + +from webob import exc + +from nova import db +from nova import crypto +from nova import exception +from nova.api.openstack import extensions + + +class KeypairController(object): + """ Keypair API controller for the Openstack API """ + + # TODO(ja): the keypair crud logic should be in nova.compute.API? + + def _gen_key(self): + """ + Generate a key + """ + # TODO(ja): crypto.generate_key_pair is currently a slow method + # and should probably be moved to a process pool? + private_key, public_key, fingerprint = crypto.generate_key_pair() + return {'private_key': private_key, + 'public_key': public_key, + 'fingerprint': fingerprint} + + def create(self, req, body): + """ + Create or import keypair. + + Sending key_name will generate a key and return private_key + and fingerprint. + + You can send a public_key to add an existing ssh key + + params: keypair object with: + key_name (required) - string + fingerprint (optional) - string + public_key (optional) - string + """ + + context = req.environ['nova.context'] + params = body['keypair'] + key_name = params['key_name'] + + # NOTE(ja): generation is slow, so shortcut invalid key_name exception + try: + db.key_pair_get(context, context.user_id, key_name) + raise exception.KeyPairExists(key_name=key_name) + except exception.NotFound: + pass + + keypair = {'user_id': context.user_id, + 'name': key_name} + + # import if public_key is sent + if 'public_key' in params: + keypair['public_key'] = params['public_key'] + keypair['fingerprint'] = params.get('fingerprint', None) + else: + generated_key = self._gen_key() + keypair['private_key'] = generated_key['private_key'] + keypair['public_key'] = generated_key['public_key'] + keypair['fingerprint'] = generated_key['fingerprint'] + + db.key_pair_create(context, keypair) + return {'keypair': keypair} + + def delete(self, req, name): + """ + Delete a keypair with a given name + """ + context = req.environ['nova.context'] + db.key_pair_destroy(context, context.user_id, name) + return exc.HTTPAccepted() + + def index(self, req): + """ + List of keypairs for a user + """ + context = req.environ['nova.context'] + key_pairs = db.key_pair_get_all_by_user(context, context.user_id) + rval = [] + for key_pair in key_pairs: + rval.append({ + 'name': key_pair['name'], + 'key_name': key_pair['name'], + 'fingerprint': key_pair['fingerprint'], + }) + + return {'keypairs': rval} + + +class Keypairs(extensions.ExtensionDescriptor): + + def get_name(self): + return "Keypairs" + + def get_alias(self): + return "os-keypairs" + + def get_description(self): + return "Keypair Support" + + def get_namespace(self): + return \ + "http://docs.openstack.org/ext/keypairs/api/v1.1" + + def get_updated(self): + return "2011-08-08T00:00:00+00:00" + + def get_resources(self): + resources = [] + + res = extensions.ResourceExtension( + 'os-keypairs', + KeypairController()) + + resources.append(res) + return resources -- cgit From 057b6ad650013a952f88f6e02f3e3db0164084d1 Mon Sep 17 00:00:00 2001 From: Jesse Andrews Date: Tue, 9 Aug 2011 13:00:13 -0700 Subject: added tests - list doesn't pass due to unicode issues --- nova/api/openstack/contrib/keypairs.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/keypairs.py b/nova/api/openstack/contrib/keypairs.py index 879bd9712..8435494e1 100644 --- a/nova/api/openstack/contrib/keypairs.py +++ b/nova/api/openstack/contrib/keypairs.py @@ -23,19 +23,20 @@ from nova import db from nova import crypto from nova import exception from nova.api.openstack import extensions - +import os +import shutil +import tempfile class KeypairController(object): """ Keypair API controller for the Openstack API """ - # TODO(ja): the keypair crud logic should be in nova.compute.API? + # TODO(ja): both this file and nova.api.ec2.cloud.py have similar logic. + # move the common keypair logic to nova.compute.API? def _gen_key(self): """ Generate a key """ - # TODO(ja): crypto.generate_key_pair is currently a slow method - # and should probably be moved to a process pool? private_key, public_key, fingerprint = crypto.generate_key_pair() return {'private_key': private_key, 'public_key': public_key, @@ -52,7 +53,6 @@ class KeypairController(object): params: keypair object with: key_name (required) - string - fingerprint (optional) - string public_key (optional) - string """ @@ -72,8 +72,14 @@ class KeypairController(object): # import if public_key is sent if 'public_key' in params: + tmpdir = tempfile.mkdtemp() + fn = os.path.join(tmpdir, 'import.pub') + with open(fn, 'w') as pub: + pub.write(params['public_key']) + fingerprint = crypto.generate_fingerprint(fn) + shutil.rmtree(tmpdir) keypair['public_key'] = params['public_key'] - keypair['fingerprint'] = params.get('fingerprint', None) + keypair['fingerprint'] = fingerprint else: generated_key = self._gen_key() keypair['private_key'] = generated_key['private_key'] @@ -83,12 +89,12 @@ class KeypairController(object): db.key_pair_create(context, keypair) return {'keypair': keypair} - def delete(self, req, name): + def delete(self, req, id): """ Delete a keypair with a given name """ context = req.environ['nova.context'] - db.key_pair_destroy(context, context.user_id, name) + db.key_pair_destroy(context, context.user_id, id) return exc.HTTPAccepted() def index(self, req): @@ -99,11 +105,11 @@ class KeypairController(object): key_pairs = db.key_pair_get_all_by_user(context, context.user_id) rval = [] for key_pair in key_pairs: - rval.append({ + rval.append({'keypair': { 'name': key_pair['name'], 'key_name': key_pair['name'], 'fingerprint': key_pair['fingerprint'], - }) + }}) return {'keypairs': rval} -- cgit From 131b2185e23567895e3f87cdfe9c2822d18910b2 Mon Sep 17 00:00:00 2001 From: Jesse Andrews Date: Tue, 9 Aug 2011 16:12:59 -0700 Subject: tests pass --- nova/api/openstack/contrib/keypairs.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/keypairs.py b/nova/api/openstack/contrib/keypairs.py index 8435494e1..d718846f1 100644 --- a/nova/api/openstack/contrib/keypairs.py +++ b/nova/api/openstack/contrib/keypairs.py @@ -46,29 +46,29 @@ class KeypairController(object): """ Create or import keypair. - Sending key_name will generate a key and return private_key + Sending name will generate a key and return private_key and fingerprint. You can send a public_key to add an existing ssh key params: keypair object with: - key_name (required) - string + name (required) - string public_key (optional) - string """ context = req.environ['nova.context'] params = body['keypair'] - key_name = params['key_name'] + name = params['name'] - # NOTE(ja): generation is slow, so shortcut invalid key_name exception + # NOTE(ja): generation is slow, so shortcut invalid name exception try: - db.key_pair_get(context, context.user_id, key_name) - raise exception.KeyPairExists(key_name=key_name) + db.key_pair_get(context, context.user_id, name) + raise exception.KeyPairExists(key_name=name) except exception.NotFound: pass keypair = {'user_id': context.user_id, - 'name': key_name} + 'name': name} # import if public_key is sent if 'public_key' in params: @@ -107,7 +107,7 @@ class KeypairController(object): for key_pair in key_pairs: rval.append({'keypair': { 'name': key_pair['name'], - 'key_name': key_pair['name'], + 'public_key': key_pair['public_key'], 'fingerprint': key_pair['fingerprint'], }}) -- cgit From 0719b038ba1548f98668991507c001eb18c82981 Mon Sep 17 00:00:00 2001 From: Jesse Andrews Date: Tue, 9 Aug 2011 17:22:01 -0700 Subject: import formatting - thx --- nova/api/openstack/contrib/keypairs.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/keypairs.py b/nova/api/openstack/contrib/keypairs.py index d718846f1..201648ab5 100644 --- a/nova/api/openstack/contrib/keypairs.py +++ b/nova/api/openstack/contrib/keypairs.py @@ -17,15 +17,17 @@ """ Keypair management extension""" +import os +import shutil +import tempfile + from webob import exc -from nova import db from nova import crypto +from nova import db from nova import exception from nova.api.openstack import extensions -import os -import shutil -import tempfile + class KeypairController(object): """ Keypair API controller for the Openstack API """ -- cgit