Merge "CloudStack: catch proper HTTP exceptions"

This commit is contained in:
Zuul 2019-12-03 09:23:39 +00:00 committed by Gerrit Code Review
commit 6e9f0f0286
2 changed files with 77 additions and 23 deletions

View File

@ -173,9 +173,16 @@ class CloudStack(base.BaseHTTPMetadataService):
for _ in range(CONF.retry_count):
try:
content = self._password_client(headers=headers).strip()
except http_client.HTTPConnection as exc:
LOG.error("Getting password failed: %s", exc)
except urllib.error.HTTPError as exc:
LOG.debug("Getting password failed: %s", exc.code)
continue
except OSError as exc:
if exc.errno == 10061:
# Connection error
LOG.debug("Getting password failed due to a "
"connection failure.")
continue
raise
if not content:
LOG.warning("The Password Server did not have any "
@ -212,16 +219,23 @@ class CloudStack(base.BaseHTTPMetadataService):
for _ in range(CONF.retry_count):
try:
content = self._password_client(headers=headers).strip()
except http_client.HTTPConnection as exc:
LOG.error("Removing password failed: %s", exc)
except urllib.error.HTTPError as exc:
LOG.debug("Removing password failed: %s", exc.code)
continue
except OSError as exc:
if exc.errno == 10061:
# Connection error
LOG.debug("Removing password failed due to a "
"connection failure.")
continue
raise
if content != BAD_REQUEST:
LOG.info("The password was removed from the Password Server.")
break
else:
LOG.warning("Fail to remove the password from the "
"Password Server.")
LOG.error("Failed to remove the password from the "
"Password Server.")
def get_admin_password(self):
"""Get the admin password from the Password Server.

View File

@ -198,7 +198,8 @@ class CloudStackTest(unittest.TestCase):
@mock.patch('cloudbaseinit.metadata.services.cloudstack.CloudStack'
'._password_client')
def test_get_password_fail(self, mock_password_client):
mock_password_client.side_effect = ["", cloudstack.BAD_REQUEST,
mock_password_client.side_effect = ["",
cloudstack.BAD_REQUEST,
cloudstack.SAVED_PASSWORD]
expected_output = [
["Try to get password from the Password Server.",
@ -222,27 +223,66 @@ class CloudStackTest(unittest.TestCase):
@mock.patch('cloudbaseinit.metadata.services.cloudstack.CloudStack'
'._password_client')
def test_delete_password(self, mock_password_client):
mock_password_client.side_effect = [cloudstack.BAD_REQUEST,
cloudstack.SAVED_PASSWORD]
def test_get_password_exception(self, mock_password_client):
fake_http_error = urllib.error.HTTPError(url='127.0.0.1', code=404,
hdrs={}, fp=None,
msg='error')
fake_error = OSError(10061, "Connection error")
mock_password_client.side_effect = [fake_http_error, fake_error]
expected_output = [
'Remove the password for this instance from the '
'Password Server.',
'Fail to remove the password from the Password Server.',
["Try to get password from the Password Server.",
"Getting password failed due to a connection failure."],
'Remove the password for this instance from the '
'Password Server.',
'The password was removed from the Password Server',
["Try to get password from the Password Server.",
"Getting password failed: 404"],
]
for _ in range(2):
with testutils.LogSnatcher('cloudbaseinit.metadata.services.'
'cloudstack') as snatcher:
self.assertIsNone(self._service._get_password())
self.assertEqual(expected_output.pop(), snatcher.output)
self.assertEqual(2, mock_password_client.call_count)
@mock.patch('cloudbaseinit.metadata.services.cloudstack.CloudStack'
'._password_client')
def test_delete_password(self, mock_password_client):
fake_url_error = urllib.error.HTTPError(url='127.0.0.1', code=404,
hdrs={}, fp=None,
msg='error')
fake_connection_error = OSError(10061, "Connection error")
mock_password_client.side_effect = [cloudstack.SAVED_PASSWORD,
cloudstack.BAD_REQUEST,
fake_url_error,
fake_connection_error]
expected_output = [
['Remove the password for this instance from the '
'Password Server.',
'Removing password failed due to a connection failure.',
'Failed to remove the password from the Password Server.'],
['Remove the password for this instance from the '
'Password Server.',
'Removing password failed: 404',
'Failed to remove the password from the Password Server.'],
['Remove the password for this instance from the '
'Password Server.',
'Failed to remove the password from the Password Server.'],
['Remove the password for this instance from the '
'Password Server.',
'The password was removed from the Password Server.'],
]
with testutils.LogSnatcher('cloudbaseinit.metadata.services.'
'cloudstack') as snatcher:
self.assertIsNone(self._service._delete_password())
self.assertIsNone(self._service._delete_password())
self.assertEqual(2, mock_password_client.call_count)
for expected, output in zip(expected_output, snatcher.output):
self.assertTrue(output.startswith(expected))
expected_output_len = len(expected_output)
for _ in range(expected_output_len):
with testutils.LogSnatcher('cloudbaseinit.metadata.services.'
'cloudstack') as snatcher:
self.assertIsNone(self._service._delete_password())
self.assertEqual(expected_output.pop(), snatcher.output)
self.assertEqual(expected_output_len, mock_password_client.call_count)
@mock.patch('cloudbaseinit.metadata.services.cloudstack.CloudStack.'
'_delete_password')