Skip to content

Commit

Permalink
xenapi: stop key_init timeout failing set password
Browse files Browse the repository at this point in the history
When key-init timeout occurs, it returns None, which causes the
set-password to fail with an error casting None to int.

This code ensures it fails silently as intended.

Fixes bug 1241738
Change-Id: I080807c5728f94a6b36957efd6f2bbc44a76b1cd
  • Loading branch information
John Garbutt authored and openstack-gerrit committed Nov 22, 2013
1 parent db86ec9 commit c3aa558
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 2 deletions.
47 changes: 47 additions & 0 deletions nova/tests/virt/xenapi/test_agent.py
Expand Up @@ -204,6 +204,53 @@ def test_inject_files_skipped_when_cloud_init_installed(self):
agent.inject_files(files)


class SetAdminPasswordTestCase(AgentTestCaseBase):
@mock.patch.object(agent.XenAPIBasedAgent, '_call_agent')
@mock.patch("nova.virt.xenapi.agent.SimpleDH")
def test_exchange_key_with_agent(self, mock_simple_dh, mock_call_agent):
agent = self._create_agent(None)
instance_mock = mock_simple_dh()
instance_mock.get_public.return_value = 4321
mock_call_agent.return_value = "1234"

result = agent._exchange_key_with_agent()

mock_call_agent.assert_called_once_with('key_init', {"pub": "4321"},
success_codes=['D0'],
ignore_errors=False)
result.compute_shared.assert_called_once_with(1234)

@mock.patch.object(agent.XenAPIBasedAgent, '_call_agent')
@mock.patch.object(agent.XenAPIBasedAgent,
'_save_instance_password_if_sshkey_present')
@mock.patch.object(agent.XenAPIBasedAgent, '_exchange_key_with_agent')
def test_set_admin_password_works(self, mock_exchange, mock_save,
mock_call_agent):
mock_dh = mock.Mock(spec_set=agent.SimpleDH)
mock_dh.encrypt.return_value = "enc_pass"
mock_exchange.return_value = mock_dh
agent_inst = self._create_agent(None)

agent_inst.set_admin_password("new_pass")

mock_dh.encrypt.assert_called_once_with("new_pass\n")
mock_call_agent.assert_called_once_with('password',
{'enc_pass': 'enc_pass'})
mock_save.assert_called_once_with("new_pass")

@mock.patch.object(agent.XenAPIBasedAgent, '_add_instance_fault')
@mock.patch.object(agent.XenAPIBasedAgent, '_exchange_key_with_agent')
def test_set_admin_password_silently_fails(self, mock_exchange,
mock_add_fault):
error = exception.AgentTimeout(method="fake")
mock_exchange.side_effect = error
agent_inst = self._create_agent(None)

agent_inst.set_admin_password("new_pass")

mock_add_fault.assert_called_once_with(error, mock.ANY)


class UpgradeRequiredTestCase(test.NoDBTestCase):
def test_less_than(self):
self.assertTrue(agent.is_upgrade_required('1.2.3.4', '1.2.3.5'))
Expand Down
10 changes: 8 additions & 2 deletions nova/virt/xenapi/agent.py
Expand Up @@ -261,7 +261,8 @@ def _perform_update(self, agent_build):
def _exchange_key_with_agent(self):
dh = SimpleDH()
args = {'pub': str(dh.get_public())}
resp = self._call_agent('key_init', args, success_codes=['D0'])
resp = self._call_agent('key_init', args, success_codes=['D0'],
ignore_errors=False)
agent_pub = int(resp)
dh.compute_shared(agent_pub)
return dh
Expand All @@ -288,7 +289,12 @@ def set_admin_password(self, new_pass):
"""
LOG.debug(_('Setting admin password'), instance=self.instance)

dh = self._exchange_key_with_agent()
try:
dh = self._exchange_key_with_agent()
except exception.AgentError as error:
self._add_instance_fault(error, sys.exc_info())
return

# Some old versions of Linux and Windows agent expect trailing \n
# on password to work correctly.
enc_pass = dh.encrypt(new_pass + '\n')
Expand Down

0 comments on commit c3aa558

Please sign in to comment.