Improve "keypair data is invalid" error message

When doing a keypair-add, I was hitting a permission denied issue with
ssh-keygen -l. This turned out to be a configuration issue, but the
error message on the client side was pretty unhelpful with debugging
the issue:

  BadRequest: Keypair data is invalid (HTTP 400)

Fix that so we get:

  BadRequest: Keypair data is invalid: failed to generate fingerprint (HTTP 400)

Also fix the other uses of InvalidKeypair so we include the general
"keypair data is invalid" prefix.

Change-Id: I209e76adaf7c18a9f2f2dbb6da62db6c1cd9461e
This commit is contained in:
Mark McLoughlin 2013-09-16 11:50:35 -07:00
parent f11dc6b3bc
commit 82910812cb
6 changed files with 27 additions and 13 deletions

View File

@ -3202,11 +3202,12 @@ class KeypairAPI(base.Base):
clean_value = "".join(x for x in key_name if x in safe_chars)
if clean_value != key_name:
raise exception.InvalidKeypair(
_("Keypair name contains unsafe characters"))
reason=_("Keypair name contains unsafe characters"))
if not 0 < len(key_name) < 256:
raise exception.InvalidKeypair(
_('Keypair name must be between 1 and 255 characters long'))
reason=_('Keypair name must be between '
'1 and 255 characters long'))
count = QUOTAS.count(context, 'key_pairs', user_id)
try:

View File

@ -141,7 +141,8 @@ def generate_fingerprint(public_key):
f.write(public_key)
return _generate_fingerprint(pubfile)
except processutils.ProcessExecutionError:
raise exception.InvalidKeypair()
raise exception.InvalidKeypair(
reason=_('failed to generate fingerprint'))
def generate_key_pair(bits=None):

View File

@ -266,7 +266,7 @@ class VolumeNotCreated(NovaException):
class InvalidKeypair(Invalid):
ec2_code = 'InvalidKeyPair.Format'
msg_fmt = _("Keypair data is invalid")
msg_fmt = _("Keypair data is invalid") + ": %(reason)s"
class InvalidRequest(Invalid):

View File

@ -109,6 +109,7 @@ class KeypairsTest(test.TestCase):
self.assertEqual(res.status_int, 400)
res_dict = jsonutils.loads(res.body)
self.assertEqual(
'Keypair data is invalid: '
'Keypair name must be between 1 and 255 characters long',
res_dict['badRequest']['message'])
@ -126,6 +127,7 @@ class KeypairsTest(test.TestCase):
self.assertEqual(res.status_int, 400)
res_dict = jsonutils.loads(res.body)
self.assertEqual(
'Keypair data is invalid: '
'Keypair name must be between 1 and 255 characters long',
res_dict['badRequest']['message'])
@ -144,6 +146,7 @@ class KeypairsTest(test.TestCase):
self.assertEqual(res.status_int, 400)
res_dict = jsonutils.loads(res.body)
self.assertEqual(
"Keypair data is invalid: "
"Keypair name contains unsafe characters",
res_dict['badRequest']['message'])
@ -261,8 +264,9 @@ class KeypairsTest(test.TestCase):
self.assertEqual(res.status_int, 400)
res_dict = jsonutils.loads(res.body)
self.assertEqual("Keypair data is invalid",
res_dict['badRequest']['message'])
self.assertEqual(
'Keypair data is invalid: failed to generate fingerprint',
res_dict['badRequest']['message'])
def test_keypair_delete(self):
req = webob.Request.blank('/v2/fake/os-keypairs/FAKE')

View File

@ -111,6 +111,7 @@ class KeypairsTest(test.TestCase):
self.assertEqual(res.status_int, 400)
res_dict = jsonutils.loads(res.body)
self.assertEqual(
'Keypair data is invalid: '
'Keypair name must be between 1 and 255 characters long',
res_dict['badRequest']['message'])
@ -128,6 +129,7 @@ class KeypairsTest(test.TestCase):
self.assertEqual(res.status_int, 400)
res_dict = jsonutils.loads(res.body)
self.assertEqual(
'Keypair data is invalid: '
'Keypair name must be between 1 and 255 characters long',
res_dict['badRequest']['message'])
@ -146,6 +148,7 @@ class KeypairsTest(test.TestCase):
self.assertEqual(res.status_int, 400)
res_dict = jsonutils.loads(res.body)
self.assertEqual(
"Keypair data is invalid: "
"Keypair name contains unsafe characters",
res_dict['badRequest']['message'])
@ -262,8 +265,9 @@ class KeypairsTest(test.TestCase):
res = req.get_response(self.app)
self.assertEqual(res.status_int, 400)
res_dict = jsonutils.loads(res.body)
self.assertEqual("Keypair data is invalid",
res_dict['badRequest']['message'])
self.assertEqual(
'Keypair data is invalid: failed to generate fingerprint',
res_dict['badRequest']['message'])
def test_keypair_delete(self):
req = webob.Request.blank('/v3/keypairs/FAKE')

View File

@ -99,18 +99,21 @@ class CreateImportSharedTestMixIn(object):
name, *args)
self.assertEqual(expected_message, unicode(exc))
def assertInvalidKeypair(self, expected_message, name):
msg = _('Keypair data is invalid') + ': ' + expected_message
self.assertKeyNameRaises(exception.InvalidKeypair, msg, name)
def test_name_too_short(self):
msg = _('Keypair name must be between 1 and 255 characters long')
self.assertKeyNameRaises(exception.InvalidKeypair, msg, '')
self.assertInvalidKeypair(msg, '')
def test_name_too_long(self):
msg = _('Keypair name must be between 1 and 255 characters long')
self.assertKeyNameRaises(exception.InvalidKeypair, msg, 'x' * 256)
self.assertInvalidKeypair(msg, 'x' * 256)
def test_invalid_chars(self):
msg = _("Keypair name contains unsafe characters")
self.assertKeyNameRaises(exception.InvalidKeypair, msg,
'* BAD CHARACTERS! *')
self.assertInvalidKeypair(msg, '* BAD CHARACTERS! *')
def test_already_exists(self):
def db_key_pair_create_duplicate(context, keypair):
@ -159,7 +162,8 @@ class ImportKeypairTestCase(KeypairAPITestCase, CreateImportSharedTestMixIn):
self.keypair_api.import_key_pair,
self.ctxt, self.ctxt.user_id, 'foo',
'bad key data')
self.assertEqual(u'Keypair data is invalid', unicode(exc))
msg = u'Keypair data is invalid: failed to generate fingerprint'
self.assertEqual(msg, unicode(exc))
class GetKeypairTestCase(KeypairAPITestCase):