BZ 765854 Making the agent fault tolerant of the network services on a host not being started
Also generally increasing test coverage on the agent
--- agent/aeolus-audrey-agent.spec.in | 2 +- agent/audrey_agent.in.py | 25 ++++++++++++++++++++++--- 2 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/agent/aeolus-audrey-agent.spec.in b/agent/aeolus-audrey-agent.spec.in index 39a106c..6e09af8 100644 --- a/agent/aeolus-audrey-agent.spec.in +++ b/agent/aeolus-audrey-agent.spec.in @@ -15,7 +15,7 @@ # Name: aeolus-audrey-agent Version: @VERSION@ -Release: 14%{?dist} +Release: 15%{?dist} Summary: The Aeolus Audrey Startup Agent
Group: Applications/System diff --git a/agent/audrey_agent.in.py b/agent/audrey_agent.in.py index 9ef7826..fb554d2 100755 --- a/agent/audrey_agent.in.py +++ b/agent/audrey_agent.in.py @@ -862,15 +862,21 @@ class CSClient(object): Description: Issue the http get to the the Config Server. ''' - return self.http.request(url, method='GET', headers=headers) + try: + return self.http.request(url, method='GET', headers=headers) + except Exception, e: + return (e, None)
def _put(self, url, body=None, headers=None): ''' Description: Issue the http put to the the Config Server. ''' - return self.http.request(url, method='PUT', - body=body, headers=headers) + try: + return self.http.request(url, method='PUT', + body=body, headers=headers) + except Exception, e: + return (e, None)
def _validate_http_status(self, status): ''' @@ -1297,6 +1303,19 @@ def audrey_script_main(client_http=None): cs_client = CSClient(**conf) if client_http: cs_client.http = client_http + # test connectivity, try and wait for it if it's not there + url = cs_client._cs_url('version') + while isinstance(cs_client._get(url)[0], Exception): + if max_retry: + max_retry-=1 + LOGGER.info('Failed attempt to contact config server') + sleep(10) + else: + LOGGER.error('Failed to connect to the Configserver') + exit(1) + + max_retry = 5 + LOGGER.info(str(cs_client))
LOGGER.debug('Get optional tooling from the Config Server')
--- agent/test_audrey_agent.py | 53 ++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 51 insertions(+), 2 deletions(-)
diff --git a/agent/test_audrey_agent.py b/agent/test_audrey_agent.py index d87c05f..e9c65bb 100644 --- a/agent/test_audrey_agent.py +++ b/agent/test_audrey_agent.py @@ -84,12 +84,18 @@ class HttpUnitTest(object): ok_response = HttpUnitTestResponse(200) not_found_response = HttpUnitTestResponse(404)
+ def __init__(self, always_404=False): + self.always_404 = always_404 + def request(self, url, method='GET', body=None, headers=None): ''' Handle request when not running live but in test environment. ''' body = '' - response = HttpUnitTest.ok_response + if self.always_404 and not url.endswith('/user-data'): + return HttpUnitTest.not_found_response, body + else: + response = HttpUnitTest.ok_response if method == 'GET': if url.find('/configs/') > -1: body = '|service|s1|parameters|param1&%s|param2&%s|' % \ @@ -113,7 +119,6 @@ class HttpUnitTest(object): body = base64.b64encode(DUMMY_USER_DATA) response = HttpUnitTest.not_found_response else: - print url response = HttpUnitTest.not_found_response #elif method == 'POST' and url.find('/params/') > -1: # body = '' @@ -134,6 +139,10 @@ class TestAudreyStarupRunCmds(unittest.TestCase): self.assertEqual("'test'\n", _run_pipe_cmd(["echo", "'test'"], ["grep", "test"])['out'])
+ def test_fail_run_cmd(self): + self.assertEqual("[Errno 2] No such file or directory", + _run_cmd(["notreal"])['err']) + def test_cmd2_fail_run_pipe_cmd(self): self.assertEqual("[Errno 2] No such file or directory", _run_pipe_cmd(["echo", "'test'"], ["notreal"])['err']) @@ -322,6 +331,24 @@ class TestAudreyStartupRequiredConfig(unittest.TestCase): print 'parse_require_config returned: ' + \ str(parse_require_config(src))
+ def test_failure_service_tag_not_found(self): + ''' + Failure Case: + - |service| not in src to parse_require_config() + ''' + src = '|notservice|blah|' + with self.assertRaises(ASError): + parse_require_config(src) + + def test_failure_no_amp_delim(self): + ''' + Failure Case: + - no delim in param token + ''' + src = '|service|blah|parameters|blah|' + with self.assertRaises(ASError): + parse_require_config(src) + class TestAudreyStartupDiscovery(unittest.TestCase): def setUp(self): ''' @@ -426,6 +453,18 @@ class TestAudreyStartupProvidesParameters(unittest.TestCase): for param in expected_params_list: self.assertTrue('%7C' + str(param) in provides)
+ def test_success_empty_params(self): + ''' + Success case: + - Exercise parse_provides_params() and generate_provides() + with valid demlims but empty input + ''' + src = '||' + params_list = parse_provides_params(src) + provides = generate_provides(src) + self.assertEqual(params_list, ['']) + self.assertEqual(provides, 'audrey_data=%7C%26%7C') + def test_success_no_params(self): ''' Success case: @@ -679,6 +718,16 @@ class TestAudreyScript(unittest.TestCase): ''' self.assertRaises(ASError, audrey_script_main)
+ def test_fail_audrey_script_main_404(self): + ''' + Perform what the audrey script will do. + ''' + cloud_info_file = 'cloud_info' + sys.argv.extend(['-p']) + _write_info_file(cloud_info_file, 'EC2') + self.assertRaises(ASError, audrey_script_main, HttpUnitTest(True)) + os.remove(cloud_info_file) + def test_empty_gen_env(self): self.assertRaises(ASError, gen_env, '', '')
aeolus-devel@lists.fedorahosted.org