Merge "Fix the issue with getting nodes by FQDNs"
This commit is contained in:
commit
b704c0f4bc
@ -12,6 +12,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
import copy
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from ansible.executor import task_queue_manager
|
from ansible.executor import task_queue_manager
|
||||||
@ -33,6 +34,8 @@ DEFAULT_ERROR_STATUSES = {STATUS_FAILED, STATUS_UNREACHABLE}
|
|||||||
|
|
||||||
SSH_COMMON_ARGS = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
|
SSH_COMMON_ARGS = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
|
||||||
|
|
||||||
|
STDOUT_LIMIT = 4096 # Symbols count
|
||||||
|
|
||||||
|
|
||||||
class AnsibleExecutionException(Exception):
|
class AnsibleExecutionException(Exception):
|
||||||
pass
|
pass
|
||||||
@ -198,6 +201,13 @@ class AnsibleRunner(object):
|
|||||||
else AnsibleExecutionException)
|
else AnsibleExecutionException)
|
||||||
raise ek(msg)
|
raise ek(msg)
|
||||||
|
|
||||||
LOG.debug('Execution result: %s' % result)
|
log_result = copy.deepcopy(result)
|
||||||
|
LOG.debug('Execution completed with %s result(s):' % len(log_result))
|
||||||
|
for lr in log_result:
|
||||||
|
if len(lr.payload['stdout']) > STDOUT_LIMIT:
|
||||||
|
lr.payload['stdout'] = (
|
||||||
|
lr.payload['stdout'][:STDOUT_LIMIT] + '... <cut>')
|
||||||
|
del lr.payload['stdout_lines']
|
||||||
|
LOG.debug(lr)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -474,9 +474,12 @@ class FuelManagement(cloud_management.CloudManagement):
|
|||||||
|
|
||||||
def _get_cloud_hosts(self):
|
def _get_cloud_hosts(self):
|
||||||
if not self.cached_cloud_hosts:
|
if not self.cached_cloud_hosts:
|
||||||
task = {'command': 'fuel2 node list -f json'}
|
task = {'command': 'fuel node --json'}
|
||||||
result = self.execute_on_master_node(task)
|
result = self.execute_on_master_node(task)
|
||||||
return json.loads(result[0].payload['stdout'])
|
for r in json.loads(result[0].payload['stdout']):
|
||||||
|
host = {'ip': r['ip'], 'mac': r['mac'], 'fqdn': r['fqdn']}
|
||||||
|
self.cached_cloud_hosts.append(host)
|
||||||
|
self.fqdn_to_hosts[host['fqdn']] = host
|
||||||
|
|
||||||
return self.cached_cloud_hosts
|
return self.cached_cloud_hosts
|
||||||
|
|
||||||
@ -501,24 +504,18 @@ class FuelManagement(cloud_management.CloudManagement):
|
|||||||
else:
|
else:
|
||||||
return self.cloud_executor.execute(hosts, task, [])
|
return self.cloud_executor.execute(hosts, task, [])
|
||||||
|
|
||||||
def _retrieve_hosts_fqdn(self):
|
|
||||||
for host in self._get_cloud_hosts():
|
|
||||||
host['fqdn'] = 'node-%s.domain.tld' % host['id']
|
|
||||||
self.fqdn_to_hosts[host['fqdn']] = host
|
|
||||||
|
|
||||||
def get_nodes(self, fqdns=None):
|
def get_nodes(self, fqdns=None):
|
||||||
"""Get nodes in the cloud
|
"""Get nodes in the cloud
|
||||||
|
|
||||||
This function returns NodesCollection representing all nodes in the
|
This function returns NodesCollection representing all nodes in the
|
||||||
cloud or only those that has specified FQDNs.
|
cloud or only those that were specified by FQDNs.
|
||||||
:param fqdns: list of FQDNs or None to retrieve all nodes
|
:param fqdns: list of FQDNs or None to retrieve all nodes
|
||||||
:return: NodesCollection
|
:return: NodesCollection
|
||||||
"""
|
"""
|
||||||
|
hosts = self._get_cloud_hosts()
|
||||||
|
|
||||||
if fqdns:
|
if fqdns:
|
||||||
# return only specified
|
|
||||||
logging.debug('Trying to find nodes with FQDNs: %s', fqdns)
|
logging.debug('Trying to find nodes with FQDNs: %s', fqdns)
|
||||||
if not self.fqdn_to_hosts:
|
|
||||||
self._retrieve_hosts_fqdn()
|
|
||||||
hosts = list()
|
hosts = list()
|
||||||
for fqdn in fqdns:
|
for fqdn in fqdns:
|
||||||
if fqdn in self.fqdn_to_hosts:
|
if fqdn in self.fqdn_to_hosts:
|
||||||
@ -527,9 +524,7 @@ class FuelManagement(cloud_management.CloudManagement):
|
|||||||
raise error.NodeCollectionError(
|
raise error.NodeCollectionError(
|
||||||
'Node with FQDN \'%s\' not found!' % fqdn)
|
'Node with FQDN \'%s\' not found!' % fqdn)
|
||||||
logging.debug('The following nodes were found: %s', hosts)
|
logging.debug('The following nodes were found: %s', hosts)
|
||||||
else:
|
|
||||||
# return all nodes
|
|
||||||
hosts = self._get_cloud_hosts()
|
|
||||||
return FuelNodeCollection(cloud_management=self,
|
return FuelNodeCollection(cloud_management=self,
|
||||||
power_management=self.power_management,
|
power_management=self.power_management,
|
||||||
hosts=hosts)
|
hosts=hosts)
|
||||||
|
@ -205,3 +205,23 @@ class AnsibleRunnerTestCase(test.TestCase):
|
|||||||
err = self.assertRaises(executor.AnsibleExecutionException,
|
err = self.assertRaises(executor.AnsibleExecutionException,
|
||||||
ex.execute, my_hosts, my_tasks, my_statuses)
|
ex.execute, my_hosts, my_tasks, my_statuses)
|
||||||
self.assertEqual(type(err), executor.AnsibleExecutionException)
|
self.assertEqual(type(err), executor.AnsibleExecutionException)
|
||||||
|
|
||||||
|
@mock.patch('copy.deepcopy')
|
||||||
|
@mock.patch('os_faults.ansible.executor.AnsibleRunner.run_playbook')
|
||||||
|
def test_execute_stdout_is_more_than_stdout_limit(
|
||||||
|
self, mock_run_playbook, mock_deepcopy):
|
||||||
|
result = mock.Mock()
|
||||||
|
result.payload = {'stdout': 'a' * (executor.STDOUT_LIMIT + 1),
|
||||||
|
'stdout_lines': 'a' * (executor.STDOUT_LIMIT + 1)}
|
||||||
|
mock_run_playbook.return_value = [result]
|
||||||
|
|
||||||
|
mock_deepcopy.return_value = [result]
|
||||||
|
log_result = mock_deepcopy.return_value[0]
|
||||||
|
|
||||||
|
my_hosts = ['0.0.0.0', '255.255.255.255']
|
||||||
|
my_tasks = 'my_task'
|
||||||
|
ex = executor.AnsibleRunner()
|
||||||
|
ex.execute(my_hosts, my_tasks)
|
||||||
|
|
||||||
|
self.assertEqual('a' * executor.STDOUT_LIMIT + '... <cut>',
|
||||||
|
log_result.payload['stdout'])
|
||||||
|
@ -27,8 +27,10 @@ class FuelManagementTestCase(test.TestCase):
|
|||||||
super(FuelManagementTestCase, self).setUp()
|
super(FuelManagementTestCase, self).setUp()
|
||||||
|
|
||||||
self.fake_ansible_result = fakes.FakeAnsibleResult(
|
self.fake_ansible_result = fakes.FakeAnsibleResult(
|
||||||
payload={'stdout': '[{"ip": "10.0.0.2", "mac": "02", "id": "2"},'
|
payload={
|
||||||
' {"ip": "10.0.0.3", "mac": "03", "id": "3"}]'})
|
'stdout': '[{"ip": "10.0.0.2", "mac": "02", "fqdn": "node-2"},'
|
||||||
|
' {"ip": "10.0.0.3", "mac": "03", "fqdn": "node-3"}]'
|
||||||
|
})
|
||||||
|
|
||||||
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
|
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
|
||||||
def test_verify(self, mock_ansible_runner):
|
def test_verify(self, mock_ansible_runner):
|
||||||
@ -45,7 +47,7 @@ class FuelManagementTestCase(test.TestCase):
|
|||||||
fuel_managment.verify()
|
fuel_managment.verify()
|
||||||
|
|
||||||
ansible_runner_inst.execute.assert_has_calls([
|
ansible_runner_inst.execute.assert_has_calls([
|
||||||
mock.call(['fuel.local'], {'command': 'fuel2 node list -f json'}),
|
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'], {'command': 'hostname'}),
|
mock.call(['10.0.0.2', '10.0.0.3'], {'command': 'hostname'}),
|
||||||
])
|
])
|
||||||
|
|
||||||
@ -60,12 +62,12 @@ class FuelManagementTestCase(test.TestCase):
|
|||||||
nodes = fuel_managment.get_nodes()
|
nodes = fuel_managment.get_nodes()
|
||||||
|
|
||||||
ansible_runner_inst.execute.assert_has_calls([
|
ansible_runner_inst.execute.assert_has_calls([
|
||||||
mock.call(['fuel.local'], {'command': 'fuel2 node list -f json'}),
|
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
|
||||||
])
|
])
|
||||||
|
|
||||||
self.assertEqual(nodes.hosts,
|
self.assertEqual(nodes.hosts,
|
||||||
[{'ip': '10.0.0.2', 'mac': '02', "id": "2"},
|
[{'ip': '10.0.0.2', 'mac': '02', "fqdn": "node-2"},
|
||||||
{'ip': '10.0.0.3', 'mac': '03', "id": "3"}])
|
{'ip': '10.0.0.3', 'mac': '03', "fqdn": "node-3"}])
|
||||||
|
|
||||||
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
|
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
|
||||||
def test_execute_on_cloud(self, mock_ansible_runner):
|
def test_execute_on_cloud(self, mock_ansible_runner):
|
||||||
@ -84,7 +86,7 @@ class FuelManagementTestCase(test.TestCase):
|
|||||||
nodes.get_ips(), {'command': 'mycmd'}, raise_on_error=False)
|
nodes.get_ips(), {'command': 'mycmd'}, raise_on_error=False)
|
||||||
|
|
||||||
ansible_runner_inst.execute.assert_has_calls([
|
ansible_runner_inst.execute.assert_has_calls([
|
||||||
mock.call(['fuel.local'], {'command': 'fuel2 node list -f json'}),
|
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'], {'command': 'mycmd'}, []),
|
mock.call(['10.0.0.2', '10.0.0.3'], {'command': 'mycmd'}, []),
|
||||||
])
|
])
|
||||||
|
|
||||||
@ -100,11 +102,10 @@ class FuelManagementTestCase(test.TestCase):
|
|||||||
'address': 'fuel.local',
|
'address': 'fuel.local',
|
||||||
'username': 'root',
|
'username': 'root',
|
||||||
})
|
})
|
||||||
nodes = fuel_managment.get_nodes(fqdns=['node-3.domain.tld'])
|
nodes = fuel_managment.get_nodes(fqdns=['node-3'])
|
||||||
|
|
||||||
self.assertEqual(nodes.hosts, [{'ip': '10.0.0.3',
|
self.assertEqual(nodes.hosts,
|
||||||
'mac': '03', 'id': '3',
|
[{'ip': '10.0.0.3', 'mac': '03', 'fqdn': 'node-3'}])
|
||||||
'fqdn': 'node-3.domain.tld'}])
|
|
||||||
|
|
||||||
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
|
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
|
||||||
@ddt.data(('keystone', fuel.KeystoneService),
|
@ddt.data(('keystone', fuel.KeystoneService),
|
||||||
@ -136,9 +137,9 @@ class FuelManagementTestCase(test.TestCase):
|
|||||||
|
|
||||||
nodes = service.get_nodes()
|
nodes = service.get_nodes()
|
||||||
ansible_runner_inst.execute.assert_has_calls([
|
ansible_runner_inst.execute.assert_has_calls([
|
||||||
mock.call(['fuel.local'], {'command': 'fuel2 node list -f json'}),
|
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||||
{'command': service_cls.GET_NODES_CMD}, []),
|
{'command': service_cls.GET_NODES_CMD}, []),
|
||||||
])
|
])
|
||||||
self.assertEqual(nodes.hosts, [{'ip': '10.0.0.3',
|
self.assertEqual(nodes.hosts,
|
||||||
'mac': '03', 'id': '3'}])
|
[{'ip': '10.0.0.3', 'mac': '03', "fqdn": "node-3"}])
|
||||||
|
@ -28,8 +28,10 @@ class FuelServiceTestCase(test.TestCase):
|
|||||||
super(FuelServiceTestCase, self).setUp()
|
super(FuelServiceTestCase, self).setUp()
|
||||||
self.conf = {'address': 'fuel.local', 'username': 'root'}
|
self.conf = {'address': 'fuel.local', 'username': 'root'}
|
||||||
self.fake_ansible_result = fakes.FakeAnsibleResult(
|
self.fake_ansible_result = fakes.FakeAnsibleResult(
|
||||||
payload={'stdout': '[{"ip": "10.0.0.2", "mac": "02", "id": "2"},'
|
payload={
|
||||||
' {"ip": "10.0.0.3", "mac": "03", "id": "3"}]'})
|
'stdout': '[{"ip": "10.0.0.2", "mac": "02", "fqdn": "node-2"},'
|
||||||
|
' {"ip": "10.0.0.3", "mac": "03", "fqdn": "node-3"}]'
|
||||||
|
})
|
||||||
|
|
||||||
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
|
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
|
||||||
@ddt.data(('keystone', fuel.KeystoneService),
|
@ddt.data(('keystone', fuel.KeystoneService),
|
||||||
@ -66,7 +68,7 @@ class FuelServiceTestCase(test.TestCase):
|
|||||||
|
|
||||||
service.kill()
|
service.kill()
|
||||||
ansible_runner_inst.execute.assert_has_calls([
|
ansible_runner_inst.execute.assert_has_calls([
|
||||||
mock.call(['fuel.local'], {'command': 'fuel2 node list -f json'}),
|
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||||
{'command': service_cls.GET_NODES_CMD}, []),
|
{'command': service_cls.GET_NODES_CMD}, []),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||||
@ -108,7 +110,7 @@ class FuelServiceTestCase(test.TestCase):
|
|||||||
|
|
||||||
service.freeze()
|
service.freeze()
|
||||||
ansible_runner_inst.execute.assert_has_calls([
|
ansible_runner_inst.execute.assert_has_calls([
|
||||||
mock.call(['fuel.local'], {'command': 'fuel2 node list -f json'}),
|
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||||
{'command': service_cls.GET_NODES_CMD}, []),
|
{'command': service_cls.GET_NODES_CMD}, []),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||||
@ -151,7 +153,7 @@ class FuelServiceTestCase(test.TestCase):
|
|||||||
delay_sec = 10
|
delay_sec = 10
|
||||||
service.freeze(nodes=None, sec=delay_sec)
|
service.freeze(nodes=None, sec=delay_sec)
|
||||||
ansible_runner_inst.execute.assert_has_calls([
|
ansible_runner_inst.execute.assert_has_calls([
|
||||||
mock.call(['fuel.local'], {'command': 'fuel2 node list -f json'}),
|
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||||
{'command': service_cls.GET_NODES_CMD}, []),
|
{'command': service_cls.GET_NODES_CMD}, []),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||||
@ -194,7 +196,7 @@ class FuelServiceTestCase(test.TestCase):
|
|||||||
|
|
||||||
service.unfreeze()
|
service.unfreeze()
|
||||||
ansible_runner_inst.execute.assert_has_calls([
|
ansible_runner_inst.execute.assert_has_calls([
|
||||||
mock.call(['fuel.local'], {'command': 'fuel2 node list -f json'}),
|
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||||
{'command': service_cls.GET_NODES_CMD}, []),
|
{'command': service_cls.GET_NODES_CMD}, []),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||||
@ -225,7 +227,7 @@ class FuelServiceTestCase(test.TestCase):
|
|||||||
|
|
||||||
service.unplug()
|
service.unplug()
|
||||||
ansible_runner_inst.execute.assert_has_calls([
|
ansible_runner_inst.execute.assert_has_calls([
|
||||||
mock.call(['fuel.local'], {'command': 'fuel2 node list -f json'}),
|
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||||
{'command': service_cls.GET_NODES_CMD}, []),
|
{'command': service_cls.GET_NODES_CMD}, []),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||||
@ -257,7 +259,7 @@ class FuelServiceTestCase(test.TestCase):
|
|||||||
|
|
||||||
service.plug()
|
service.plug()
|
||||||
ansible_runner_inst.execute.assert_has_calls([
|
ansible_runner_inst.execute.assert_has_calls([
|
||||||
mock.call(['fuel.local'], {'command': 'fuel2 node list -f json'}),
|
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||||
{'command': service_cls.GET_NODES_CMD}, []),
|
{'command': service_cls.GET_NODES_CMD}, []),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||||
@ -298,7 +300,7 @@ class FuelServiceTestCase(test.TestCase):
|
|||||||
|
|
||||||
service.restart()
|
service.restart()
|
||||||
ansible_runner_inst.execute.assert_has_calls([
|
ansible_runner_inst.execute.assert_has_calls([
|
||||||
mock.call(['fuel.local'], {'command': 'fuel2 node list -f json'}),
|
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||||
{'command': service_cls.GET_NODES_CMD}, []),
|
{'command': service_cls.GET_NODES_CMD}, []),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||||
@ -328,7 +330,7 @@ class FuelServiceTestCase(test.TestCase):
|
|||||||
self.assertEqual('Task failed on some nodes', str(exception))
|
self.assertEqual('Task failed on some nodes', str(exception))
|
||||||
|
|
||||||
ansible_runner_inst.execute.assert_has_calls([
|
ansible_runner_inst.execute.assert_has_calls([
|
||||||
mock.call(['fuel.local'], {'command': 'fuel2 node list -f json'}),
|
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||||
{'command': service.GET_NODES_CMD}, []),
|
{'command': service.GET_NODES_CMD}, []),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||||
@ -355,7 +357,7 @@ class FuelServiceTestCase(test.TestCase):
|
|||||||
self.assertEqual('Node collection is empty', str(exception))
|
self.assertEqual('Node collection is empty', str(exception))
|
||||||
|
|
||||||
ansible_runner_inst.execute.assert_has_calls([
|
ansible_runner_inst.execute.assert_has_calls([
|
||||||
mock.call(['fuel.local'], {'command': 'fuel2 node list -f json'}),
|
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
|
||||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||||
{'command': service.GET_NODES_CMD}, []),
|
{'command': service.GET_NODES_CMD}, []),
|
||||||
])
|
])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user