[tcpcloud] Additional configuration parameters
* Added get_ips_cmd parameter that specifies salt command that returns ip address of minion. * Added slave_direct_ssh parameter that enables/disables using of salt master node as ssh proxy. Change-Id: Ida4a2e0e7e549d7d9313a1c11188d38cdc49e475 Signed-off-by: Anton Studenov <astudenov@mirantis.com>
This commit is contained in:
parent
3954065549
commit
abf60b09ca
|
@ -24,6 +24,10 @@ class PowerManagementError(OSFError):
|
|||
"""Base Error class for Power Management API"""
|
||||
|
||||
|
||||
class CloudManagementError(OSFError):
|
||||
"""Base Error class for Cloud Management API"""
|
||||
|
||||
|
||||
class ServiceError(OSFError):
|
||||
"""Base Error class for Service API"""
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ from os_faults.api import cloud_management
|
|||
from os_faults.api import node_collection
|
||||
from os_faults.api import node_discover
|
||||
from os_faults.common import service
|
||||
from os_faults import error
|
||||
from os_faults import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
@ -246,8 +247,9 @@ class TCPCloudManagement(cloud_management.CloudManagement,
|
|||
'slave_username': {'type': 'string'},
|
||||
'master_sudo': {'type': 'boolean'},
|
||||
'slave_sudo': {'type': 'boolean'},
|
||||
'slave_iface': {'type': 'string'},
|
||||
'slave_name_regexp': {'type': 'string'},
|
||||
'slave_direct_ssh': {'type': 'boolean'},
|
||||
'get_ips_cmd': {'type': 'string'},
|
||||
},
|
||||
'required': ['address', 'username'],
|
||||
'additionalProperties': False,
|
||||
|
@ -262,6 +264,11 @@ class TCPCloudManagement(cloud_management.CloudManagement,
|
|||
self.slave_username = cloud_management_params.get(
|
||||
'slave_username', self.username)
|
||||
self.private_key_file = cloud_management_params.get('private_key_file')
|
||||
self.slave_direct_ssh = cloud_management_params.get(
|
||||
'slave_direct_ssh', False)
|
||||
use_jump = not self.slave_direct_ssh
|
||||
self.get_ips_cmd = cloud_management_params.get(
|
||||
'get_ips_cmd', 'pillar.get _param:single_address')
|
||||
|
||||
self.master_node_executor = executor.AnsibleRunner(
|
||||
remote_user=self.username,
|
||||
|
@ -271,12 +278,10 @@ class TCPCloudManagement(cloud_management.CloudManagement,
|
|||
self.cloud_executor = executor.AnsibleRunner(
|
||||
remote_user=self.slave_username,
|
||||
private_key_file=self.private_key_file,
|
||||
jump_host=self.master_node_address,
|
||||
jump_user=self.username,
|
||||
jump_host=self.master_node_address if use_jump else None,
|
||||
jump_user=self.username if use_jump else None,
|
||||
become=cloud_management_params.get('slave_sudo'))
|
||||
|
||||
self.slave_iface = cloud_management_params.get('slave_iface', 'eth0')
|
||||
|
||||
# get all nodes except salt master (that has cfg* hostname) by default
|
||||
self.slave_name_regexp = cloud_management_params.get(
|
||||
'slave_name_regexp', '^(?!cfg|mon)')
|
||||
|
@ -295,17 +300,33 @@ class TCPCloudManagement(cloud_management.CloudManagement,
|
|||
|
||||
LOG.info('Connected to cloud successfully!')
|
||||
|
||||
def _run_salt(self, command):
|
||||
cmd = "salt -E '{}' {} --out=yaml".format(
|
||||
self.slave_name_regexp, command)
|
||||
result = self._execute_on_master_node({'command': cmd})
|
||||
return yaml.load(result[0].payload['stdout'])
|
||||
|
||||
def discover_hosts(self):
|
||||
if not self.cached_cloud_hosts:
|
||||
cmd = "salt -E '{}' network.interfaces --out=yaml".format(
|
||||
self.slave_name_regexp)
|
||||
result = self._execute_on_master_node({'command': cmd})
|
||||
stdout = result[0].payload['stdout']
|
||||
for fqdn, net_data in yaml.load(stdout).items():
|
||||
host = node_collection.Host(
|
||||
ip=net_data[self.slave_iface]['inet'][0]['address'],
|
||||
mac=net_data[self.slave_iface]['hwaddr'],
|
||||
fqdn=fqdn)
|
||||
interfaces = self._run_salt("network.interfaces")
|
||||
ips = self._run_salt(self.get_ips_cmd)
|
||||
|
||||
for fqdn, ip in ips.items():
|
||||
node_ifaces = interfaces[fqdn]
|
||||
|
||||
mac = None
|
||||
for iface_name, net_data in node_ifaces.items():
|
||||
iface_ips = [data['address']
|
||||
for data in net_data.get('inet', [])]
|
||||
if ip in iface_ips:
|
||||
mac = net_data['hwaddr']
|
||||
break
|
||||
else:
|
||||
raise error.CloudManagementError(
|
||||
"Can't find ip {} on node {} with node_ifaces:\n{}"
|
||||
"".format(ip, fqdn, yaml.dump(node_ifaces)))
|
||||
|
||||
host = node_collection.Host(ip=ip, mac=mac, fqdn=fqdn)
|
||||
self.cached_cloud_hosts.append(host)
|
||||
self.cached_cloud_hosts = sorted(self.cached_cloud_hosts)
|
||||
|
||||
|
|
|
@ -33,19 +33,36 @@ class TCPCloudManagementTestCase(test.TestCase):
|
|||
' hwaddr: 09:7b:74:90:63:c2\n'
|
||||
' inet:\n'
|
||||
' - address: 10.0.0.2\n'
|
||||
' eth2:\n'
|
||||
' hwaddr: 00:00:00:00:00:02\n'
|
||||
' inet:\n'
|
||||
' - address: 192.168.1.2\n'
|
||||
'cmp02.mk20.local:\n'
|
||||
' eth1:\n'
|
||||
' hwaddr: 00:00:00:00:00:03\n'
|
||||
' inet:\n'
|
||||
' - address: 192.168.1.3\n'
|
||||
' eth2:\n'
|
||||
' hwaddr: 09:7b:74:90:63:c3\n'
|
||||
' inet:\n'
|
||||
' - address: 10.0.0.3\n'
|
||||
})
|
||||
self.fake_node_ip_result = fakes.FakeAnsibleResult(
|
||||
payload={
|
||||
'stdout': 'cmp01.mk20.local:\n'
|
||||
' 10.0.0.2\n'
|
||||
'cmp02.mk20.local:\n'
|
||||
' 10.0.0.3\n'
|
||||
})
|
||||
|
||||
self.tcp_conf = {
|
||||
'address': 'tcp.local',
|
||||
'username': 'root',
|
||||
'slave_iface': 'eth1',
|
||||
}
|
||||
self.get_nodes_cmd = (
|
||||
"salt -E '^(?!cfg|mon)' network.interfaces --out=yaml")
|
||||
self.get_ips_cmd = ("salt -E '^(?!cfg|mon)' "
|
||||
"pillar.get _param:single_address --out=yaml")
|
||||
|
||||
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
|
||||
@ddt.data((
|
||||
|
@ -69,6 +86,15 @@ class TCPCloudManagementTestCase(test.TestCase):
|
|||
remote_user='ubuntu'),
|
||||
mock.call(become=True, jump_host='tcp.local', jump_user='ubuntu',
|
||||
private_key_file='/path/id_rsa', remote_user='root'))
|
||||
), (
|
||||
dict(address='tcp.local', username='ubuntu',
|
||||
slave_username='root', slave_sudo=True,
|
||||
private_key_file='/path/id_rsa',
|
||||
slave_direct_ssh=True),
|
||||
(mock.call(become=None, private_key_file='/path/id_rsa',
|
||||
remote_user='ubuntu'),
|
||||
mock.call(become=True, jump_host=None, jump_user=None,
|
||||
private_key_file='/path/id_rsa', remote_user='root'))
|
||||
))
|
||||
@ddt.unpack
|
||||
def test_init(self, config, expected_runner_calls, mock_ansible_runner):
|
||||
|
@ -85,6 +111,7 @@ class TCPCloudManagementTestCase(test.TestCase):
|
|||
ansible_runner_inst = mock_ansible_runner.return_value
|
||||
ansible_runner_inst.execute.side_effect = [
|
||||
[self.fake_ansible_result],
|
||||
[self.fake_node_ip_result],
|
||||
[fakes.FakeAnsibleResult(payload={'stdout': ''}),
|
||||
fakes.FakeAnsibleResult(payload={'stdout': ''})],
|
||||
]
|
||||
|
@ -93,20 +120,27 @@ class TCPCloudManagementTestCase(test.TestCase):
|
|||
tcp_managment.verify()
|
||||
|
||||
get_nodes_cmd = "salt -E '(ctl*|cmp*)' network.interfaces --out=yaml"
|
||||
get_ips_cmd = ("salt -E '(ctl*|cmp*)' "
|
||||
"pillar.get _param:single_address --out=yaml")
|
||||
ansible_runner_inst.execute.assert_has_calls([
|
||||
mock.call(['tcp.local'], {'command': get_nodes_cmd}),
|
||||
mock.call(['tcp.local'], {'command': get_ips_cmd}),
|
||||
mock.call(['10.0.0.2', '10.0.0.3'], {'command': 'hostname'}),
|
||||
])
|
||||
|
||||
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
|
||||
def test_get_nodes(self, mock_ansible_runner):
|
||||
ansible_runner_inst = mock_ansible_runner.return_value
|
||||
ansible_runner_inst.execute.side_effect = [[self.fake_ansible_result]]
|
||||
ansible_runner_inst.execute.side_effect = [
|
||||
[self.fake_ansible_result],
|
||||
[self.fake_node_ip_result],
|
||||
]
|
||||
tcp_managment = tcpcloud.TCPCloudManagement(self.tcp_conf)
|
||||
nodes = tcp_managment.get_nodes()
|
||||
|
||||
ansible_runner_inst.execute.assert_has_calls([
|
||||
mock.call(['tcp.local'], {'command': self.get_nodes_cmd}),
|
||||
mock.call(['tcp.local'], {'command': self.get_ips_cmd}),
|
||||
])
|
||||
|
||||
hosts = [
|
||||
|
@ -140,6 +174,7 @@ class TCPCloudManagementTestCase(test.TestCase):
|
|||
ansible_runner_inst = mock_ansible_runner.return_value
|
||||
ansible_runner_inst.execute.side_effect = [
|
||||
[self.fake_ansible_result],
|
||||
[self.fake_node_ip_result],
|
||||
[fakes.FakeAnsibleResult(payload={'stdout': ''}),
|
||||
fakes.FakeAnsibleResult(payload={'stdout': ''})]
|
||||
]
|
||||
|
@ -150,6 +185,7 @@ class TCPCloudManagementTestCase(test.TestCase):
|
|||
|
||||
ansible_runner_inst.execute.assert_has_calls([
|
||||
mock.call(['tcp.local'], {'command': self.get_nodes_cmd}),
|
||||
mock.call(['tcp.local'], {'command': self.get_ips_cmd}),
|
||||
mock.call(['10.0.0.2', '10.0.0.3'], {'command': 'mycmd'}, []),
|
||||
])
|
||||
|
||||
|
@ -160,7 +196,10 @@ class TCPCloudManagementTestCase(test.TestCase):
|
|||
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
|
||||
def test_get_nodes_fqdns(self, mock_ansible_runner):
|
||||
ansible_runner_inst = mock_ansible_runner.return_value
|
||||
ansible_runner_inst.execute.side_effect = [[self.fake_ansible_result]]
|
||||
ansible_runner_inst.execute.side_effect = [
|
||||
[self.fake_ansible_result],
|
||||
[self.fake_node_ip_result],
|
||||
]
|
||||
tcp_managment = tcpcloud.TCPCloudManagement(self.tcp_conf)
|
||||
nodes = tcp_managment.get_nodes(fqdns=['cmp02.mk20.local'])
|
||||
|
||||
|
@ -178,6 +217,7 @@ class TCPCloudManagementTestCase(test.TestCase):
|
|||
ansible_runner_inst = mock_ansible_runner.return_value
|
||||
ansible_runner_inst.execute.side_effect = [
|
||||
[self.fake_ansible_result],
|
||||
[self.fake_node_ip_result],
|
||||
[fakes.FakeAnsibleResult(payload={'stdout': ''},
|
||||
status=executor.STATUS_FAILED,
|
||||
host='10.0.0.2'),
|
||||
|
@ -194,6 +234,7 @@ class TCPCloudManagementTestCase(test.TestCase):
|
|||
cmd = 'bash -c "ps ax | grep \'{}\'"'.format(service_cls.GREP)
|
||||
ansible_runner_inst.execute.assert_has_calls([
|
||||
mock.call(['tcp.local'], {'command': self.get_nodes_cmd}),
|
||||
mock.call(['tcp.local'], {'command': self.get_ips_cmd}),
|
||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||
{'command': cmd}, []),
|
||||
])
|
||||
|
@ -223,12 +264,22 @@ class TcpServiceTestCase(test.TestCase):
|
|||
' inet:\n'
|
||||
' - address: 10.0.0.3\n'
|
||||
})
|
||||
self.fake_node_ip_result = fakes.FakeAnsibleResult(
|
||||
payload={
|
||||
'stdout': 'cmp01.mk20.local:\n'
|
||||
' 10.0.0.2\n'
|
||||
'cmp02.mk20.local:\n'
|
||||
' 10.0.0.3\n'
|
||||
})
|
||||
|
||||
self.tcp_conf = {
|
||||
'address': 'tcp.local',
|
||||
'username': 'root',
|
||||
}
|
||||
self.get_nodes_cmd = (
|
||||
"salt -E '^(?!cfg|mon)' network.interfaces --out=yaml")
|
||||
self.get_ips_cmd = ("salt -E '^(?!cfg|mon)' "
|
||||
"pillar.get _param:single_address --out=yaml")
|
||||
|
||||
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
|
||||
@ddt.data(*tcpcloud.TCPCloudManagement.SERVICE_NAME_TO_CLASS.items())
|
||||
|
@ -237,6 +288,7 @@ class TcpServiceTestCase(test.TestCase):
|
|||
ansible_runner_inst = mock_ansible_runner.return_value
|
||||
ansible_runner_inst.execute.side_effect = [
|
||||
[self.fake_ansible_result],
|
||||
[self.fake_node_ip_result],
|
||||
[fakes.FakeAnsibleResult(payload={'stdout': ''},
|
||||
status=executor.STATUS_FAILED,
|
||||
host='10.0.0.2'),
|
||||
|
@ -258,6 +310,7 @@ class TcpServiceTestCase(test.TestCase):
|
|||
cmd = 'bash -c "ps ax | grep \'{}\'"'.format(service_cls.GREP)
|
||||
ansible_runner_inst.execute.assert_has_calls([
|
||||
mock.call(['tcp.local'], {'command': self.get_nodes_cmd}),
|
||||
mock.call(['tcp.local'], {'command': self.get_ips_cmd}),
|
||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||
{'command': cmd}, []),
|
||||
mock.call(['10.0.0.3'], {'shell': service.RESTART_CMD}),
|
||||
|
@ -270,6 +323,7 @@ class TcpServiceTestCase(test.TestCase):
|
|||
ansible_runner_inst = mock_ansible_runner.return_value
|
||||
ansible_runner_inst.execute.side_effect = [
|
||||
[self.fake_ansible_result],
|
||||
[self.fake_node_ip_result],
|
||||
[fakes.FakeAnsibleResult(payload={'stdout': ''},
|
||||
status=executor.STATUS_FAILED,
|
||||
host='10.0.0.2'),
|
||||
|
@ -291,6 +345,7 @@ class TcpServiceTestCase(test.TestCase):
|
|||
cmd = 'bash -c "ps ax | grep \'{}\'"'.format(service_cls.GREP)
|
||||
ansible_runner_inst.execute.assert_has_calls([
|
||||
mock.call(['tcp.local'], {'command': self.get_nodes_cmd}),
|
||||
mock.call(['tcp.local'], {'command': self.get_ips_cmd}),
|
||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||
{'command': cmd}, []),
|
||||
mock.call(['10.0.0.3'], {'shell': service.TERMINATE_CMD}),
|
||||
|
@ -303,6 +358,7 @@ class TcpServiceTestCase(test.TestCase):
|
|||
ansible_runner_inst = mock_ansible_runner.return_value
|
||||
ansible_runner_inst.execute.side_effect = [
|
||||
[self.fake_ansible_result],
|
||||
[self.fake_node_ip_result],
|
||||
[fakes.FakeAnsibleResult(payload={'stdout': ''},
|
||||
status=executor.STATUS_FAILED,
|
||||
host='10.0.0.2'),
|
||||
|
@ -324,6 +380,7 @@ class TcpServiceTestCase(test.TestCase):
|
|||
cmd = 'bash -c "ps ax | grep \'{}\'"'.format(service_cls.GREP)
|
||||
ansible_runner_inst.execute.assert_has_calls([
|
||||
mock.call(['tcp.local'], {'command': self.get_nodes_cmd}),
|
||||
mock.call(['tcp.local'], {'command': self.get_ips_cmd}),
|
||||
mock.call(['10.0.0.2', '10.0.0.3'],
|
||||
{'command': cmd}, []),
|
||||
mock.call(['10.0.0.3'], {'shell': service.START_CMD}),
|
||||
|
|
Loading…
Reference in New Issue