Add serial parameter to cloud drivers
'serial' parameter defines how many hosts Ansible should manage at a single time. Change-Id: I363ffda9cebd6533d58c23ba795b702b7431301d
This commit is contained in:
parent
03fa8812fc
commit
2fafe5f9b9
@ -125,7 +125,7 @@ Options = collections.namedtuple(
|
|||||||
class AnsibleRunner(object):
|
class AnsibleRunner(object):
|
||||||
def __init__(self, remote_user='root', password=None, forks=100,
|
def __init__(self, remote_user='root', password=None, forks=100,
|
||||||
jump_host=None, jump_user=None, private_key_file=None,
|
jump_host=None, jump_user=None, private_key_file=None,
|
||||||
become=None):
|
become=None, serial=None):
|
||||||
super(AnsibleRunner, self).__init__()
|
super(AnsibleRunner, self).__init__()
|
||||||
|
|
||||||
ssh_common_args = SSH_COMMON_ARGS
|
ssh_common_args = SSH_COMMON_ARGS
|
||||||
@ -146,6 +146,7 @@ class AnsibleRunner(object):
|
|||||||
sftp_extra_args=None, scp_extra_args=None,
|
sftp_extra_args=None, scp_extra_args=None,
|
||||||
become=become, become_method='sudo', become_user='root',
|
become=become, become_method='sudo', become_user='root',
|
||||||
verbosity=100, check=False)
|
verbosity=100, check=False)
|
||||||
|
self.serial = serial or 10
|
||||||
|
|
||||||
def _run_play(self, play_source):
|
def _run_play(self, play_source):
|
||||||
host_list = play_source['hosts']
|
host_list = play_source['hosts']
|
||||||
@ -203,9 +204,10 @@ class AnsibleRunner(object):
|
|||||||
any of these statuses
|
any of these statuses
|
||||||
:return: execution result, type AnsibleExecutionRecord
|
:return: execution result, type AnsibleExecutionRecord
|
||||||
"""
|
"""
|
||||||
LOG.debug('Executing task: %s on hosts: %s', task, hosts)
|
LOG.debug('Executing task: %s on hosts: %s with serial: %s',
|
||||||
|
task, hosts, self.serial)
|
||||||
|
|
||||||
task_play = {'hosts': hosts, 'tasks': [task]}
|
task_play = {'hosts': hosts, 'tasks': [task], 'serial': self.serial}
|
||||||
result = self.run_playbook([task_play])
|
result = self.run_playbook([task_play])
|
||||||
|
|
||||||
log_result = copy.deepcopy(result)
|
log_result = copy.deepcopy(result)
|
||||||
|
@ -123,6 +123,8 @@ class DevStackManagement(cloud_management.CloudManagement,
|
|||||||
- **private_key_file** - path to key file (optional)
|
- **private_key_file** - path to key file (optional)
|
||||||
- **slaves** - list of ips for additional nodes (optional)
|
- **slaves** - list of ips for additional nodes (optional)
|
||||||
- **iface** - network interface name to retrive mac address (optional)
|
- **iface** - network interface name to retrive mac address (optional)
|
||||||
|
- **serial** - how many hosts Ansible should manage at a single time.
|
||||||
|
(optional) default: 10
|
||||||
"""
|
"""
|
||||||
|
|
||||||
NAME = 'devstack'
|
NAME = 'devstack'
|
||||||
@ -214,6 +216,7 @@ class DevStackManagement(cloud_management.CloudManagement,
|
|||||||
'items': {'type': 'string'},
|
'items': {'type': 'string'},
|
||||||
},
|
},
|
||||||
'iface': {'type': 'string'},
|
'iface': {'type': 'string'},
|
||||||
|
'serial': {'type': 'integer', 'minimum': 1},
|
||||||
},
|
},
|
||||||
'required': ['address', 'username'],
|
'required': ['address', 'username'],
|
||||||
'additionalProperties': False,
|
'additionalProperties': False,
|
||||||
@ -228,11 +231,12 @@ class DevStackManagement(cloud_management.CloudManagement,
|
|||||||
self.private_key_file = cloud_management_params.get('private_key_file')
|
self.private_key_file = cloud_management_params.get('private_key_file')
|
||||||
self.slaves = cloud_management_params.get('slaves', [])
|
self.slaves = cloud_management_params.get('slaves', [])
|
||||||
self.iface = cloud_management_params.get('iface', 'eth0')
|
self.iface = cloud_management_params.get('iface', 'eth0')
|
||||||
|
self.serial = cloud_management_params.get('serial')
|
||||||
|
|
||||||
self.cloud_executor = executor.AnsibleRunner(
|
self.cloud_executor = executor.AnsibleRunner(
|
||||||
remote_user=self.username, private_key_file=self.private_key_file,
|
remote_user=self.username, private_key_file=self.private_key_file,
|
||||||
password=cloud_management_params.get('password'),
|
password=cloud_management_params.get('password'),
|
||||||
become=False)
|
become=False, serial=self.serial)
|
||||||
|
|
||||||
self.hosts = [self.address]
|
self.hosts = [self.address]
|
||||||
if self.slaves:
|
if self.slaves:
|
||||||
|
@ -187,6 +187,8 @@ class FuelManagement(cloud_management.CloudManagement,
|
|||||||
- **private_key_file** - path to key file (optional)
|
- **private_key_file** - path to key file (optional)
|
||||||
- **slave_direct_ssh** - if *False* then fuel master is used as ssh proxy
|
- **slave_direct_ssh** - if *False* then fuel master is used as ssh proxy
|
||||||
(optional)
|
(optional)
|
||||||
|
- **serial** - how many hosts Ansible should manage at a single time.
|
||||||
|
(optional) default: 10
|
||||||
"""
|
"""
|
||||||
|
|
||||||
NAME = 'fuel'
|
NAME = 'fuel'
|
||||||
@ -501,6 +503,7 @@ class FuelManagement(cloud_management.CloudManagement,
|
|||||||
'username': {'type': 'string'},
|
'username': {'type': 'string'},
|
||||||
'private_key_file': {'type': 'string'},
|
'private_key_file': {'type': 'string'},
|
||||||
'slave_direct_ssh': {'type': 'boolean'},
|
'slave_direct_ssh': {'type': 'boolean'},
|
||||||
|
'serial': {'type': 'integer', 'minimum': 1},
|
||||||
},
|
},
|
||||||
'required': ['address', 'username'],
|
'required': ['address', 'username'],
|
||||||
'additionalProperties': False,
|
'additionalProperties': False,
|
||||||
@ -515,6 +518,7 @@ class FuelManagement(cloud_management.CloudManagement,
|
|||||||
self.private_key_file = cloud_management_params.get('private_key_file')
|
self.private_key_file = cloud_management_params.get('private_key_file')
|
||||||
self.slave_direct_ssh = cloud_management_params.get(
|
self.slave_direct_ssh = cloud_management_params.get(
|
||||||
'slave_direct_ssh', False)
|
'slave_direct_ssh', False)
|
||||||
|
self.serial = cloud_management_params.get('serial')
|
||||||
|
|
||||||
self.master_node_executor = executor.AnsibleRunner(
|
self.master_node_executor = executor.AnsibleRunner(
|
||||||
remote_user=self.username, private_key_file=self.private_key_file)
|
remote_user=self.username, private_key_file=self.private_key_file)
|
||||||
@ -525,7 +529,7 @@ class FuelManagement(cloud_management.CloudManagement,
|
|||||||
|
|
||||||
self.cloud_executor = executor.AnsibleRunner(
|
self.cloud_executor = executor.AnsibleRunner(
|
||||||
remote_user=self.username, private_key_file=self.private_key_file,
|
remote_user=self.username, private_key_file=self.private_key_file,
|
||||||
jump_host=jump_host)
|
jump_host=jump_host, serial=self.serial)
|
||||||
|
|
||||||
self.cached_cloud_hosts = list()
|
self.cached_cloud_hosts = list()
|
||||||
|
|
||||||
|
@ -128,6 +128,8 @@ class TCPCloudManagement(cloud_management.CloudManagement,
|
|||||||
- **slave_direct_ssh** - if *False* then salt master is used as ssh proxy
|
- **slave_direct_ssh** - if *False* then salt master is used as ssh proxy
|
||||||
(optional)
|
(optional)
|
||||||
- **get_ips_cmd** - salt command to get IPs of minions (optional)
|
- **get_ips_cmd** - salt command to get IPs of minions (optional)
|
||||||
|
- **serial** - how many hosts Ansible should manage at a single time.
|
||||||
|
(optional) default: 10
|
||||||
"""
|
"""
|
||||||
|
|
||||||
NAME = 'tcpcloud'
|
NAME = 'tcpcloud'
|
||||||
@ -363,6 +365,7 @@ class TCPCloudManagement(cloud_management.CloudManagement,
|
|||||||
'slave_name_regexp': {'type': 'string'},
|
'slave_name_regexp': {'type': 'string'},
|
||||||
'slave_direct_ssh': {'type': 'boolean'},
|
'slave_direct_ssh': {'type': 'boolean'},
|
||||||
'get_ips_cmd': {'type': 'string'},
|
'get_ips_cmd': {'type': 'string'},
|
||||||
|
'serial': {'type': 'integer', 'minimum': 1},
|
||||||
},
|
},
|
||||||
'required': ['address', 'username'],
|
'required': ['address', 'username'],
|
||||||
'additionalProperties': False,
|
'additionalProperties': False,
|
||||||
@ -382,6 +385,7 @@ class TCPCloudManagement(cloud_management.CloudManagement,
|
|||||||
use_jump = not self.slave_direct_ssh
|
use_jump = not self.slave_direct_ssh
|
||||||
self.get_ips_cmd = cloud_management_params.get(
|
self.get_ips_cmd = cloud_management_params.get(
|
||||||
'get_ips_cmd', 'pillar.get _param:single_address')
|
'get_ips_cmd', 'pillar.get _param:single_address')
|
||||||
|
self.serial = cloud_management_params.get('serial')
|
||||||
|
|
||||||
password = cloud_management_params.get('password')
|
password = cloud_management_params.get('password')
|
||||||
self.master_node_executor = executor.AnsibleRunner(
|
self.master_node_executor = executor.AnsibleRunner(
|
||||||
@ -396,7 +400,8 @@ class TCPCloudManagement(cloud_management.CloudManagement,
|
|||||||
private_key_file=self.private_key_file,
|
private_key_file=self.private_key_file,
|
||||||
jump_host=self.master_node_address if use_jump else None,
|
jump_host=self.master_node_address if use_jump else None,
|
||||||
jump_user=self.username if use_jump else None,
|
jump_user=self.username if use_jump else None,
|
||||||
become=cloud_management_params.get('slave_sudo'))
|
become=cloud_management_params.get('slave_sudo'),
|
||||||
|
serial=self.serial)
|
||||||
|
|
||||||
# get all nodes except salt master (that has cfg* hostname) by default
|
# get all nodes except salt master (that has cfg* hostname) by default
|
||||||
self.slave_name_regexp = cloud_management_params.get(
|
self.slave_name_regexp = cloud_management_params.get(
|
||||||
|
@ -215,7 +215,19 @@ class AnsibleRunnerTestCase(test.TestCase):
|
|||||||
ex.execute(my_hosts, my_tasks)
|
ex.execute(my_hosts, my_tasks)
|
||||||
mock_run_playbook.assert_called_once_with(
|
mock_run_playbook.assert_called_once_with(
|
||||||
[{'tasks': ['my_task'],
|
[{'tasks': ['my_task'],
|
||||||
'hosts': ['0.0.0.0', '255.255.255.255']}])
|
'hosts': ['0.0.0.0', '255.255.255.255'],
|
||||||
|
'serial': 10}])
|
||||||
|
|
||||||
|
@mock.patch('os_faults.ansible.executor.AnsibleRunner.run_playbook')
|
||||||
|
def test_execute_with_serial(self, mock_run_playbook):
|
||||||
|
my_hosts = ['0.0.0.0', '255.255.255.255']
|
||||||
|
my_tasks = 'my_task'
|
||||||
|
ex = executor.AnsibleRunner(serial=50)
|
||||||
|
ex.execute(my_hosts, my_tasks)
|
||||||
|
mock_run_playbook.assert_called_once_with(
|
||||||
|
[{'tasks': ['my_task'],
|
||||||
|
'hosts': ['0.0.0.0', '255.255.255.255'],
|
||||||
|
'serial': 50}])
|
||||||
|
|
||||||
@mock.patch('os_faults.ansible.executor.AnsibleRunner.run_playbook')
|
@mock.patch('os_faults.ansible.executor.AnsibleRunner.run_playbook')
|
||||||
def test_execute_status_unreachable(self, mock_run_playbook):
|
def test_execute_status_unreachable(self, mock_run_playbook):
|
||||||
@ -290,7 +302,8 @@ class AnsibleRunnerTestCase(test.TestCase):
|
|||||||
ex.execute([host], task)
|
ex.execute([host], task)
|
||||||
|
|
||||||
mock_debug.assert_has_calls((
|
mock_debug.assert_has_calls((
|
||||||
mock.call('Executing task: %s on hosts: %s', task, [host]),
|
mock.call('Executing task: %s on hosts: %s with serial: %s',
|
||||||
|
task, [host], 10),
|
||||||
mock.call('Execution completed with 1 result(s):'),
|
mock.call('Execution completed with 1 result(s):'),
|
||||||
mock.call(result),
|
mock.call(result),
|
||||||
))
|
))
|
||||||
|
@ -39,12 +39,13 @@ class FuelManagementTestCase(test.TestCase):
|
|||||||
dict(address='fuel.local', username='root'),
|
dict(address='fuel.local', username='root'),
|
||||||
(mock.call(private_key_file=None, remote_user='root'),
|
(mock.call(private_key_file=None, remote_user='root'),
|
||||||
mock.call(private_key_file=None, remote_user='root',
|
mock.call(private_key_file=None, remote_user='root',
|
||||||
jump_host='fuel.local'))
|
jump_host='fuel.local', serial=None))
|
||||||
), (
|
), (
|
||||||
dict(address='fuel.local', username='root', slave_direct_ssh=True),
|
dict(address='fuel.local', username='root', slave_direct_ssh=True,
|
||||||
|
serial=42),
|
||||||
(mock.call(private_key_file=None, remote_user='root'),
|
(mock.call(private_key_file=None, remote_user='root'),
|
||||||
mock.call(private_key_file=None, remote_user='root',
|
mock.call(private_key_file=None, remote_user='root',
|
||||||
jump_host=None))
|
jump_host=None, serial=42))
|
||||||
))
|
))
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test_init(self, config, expected_runner_calls, mock_ansible_runner):
|
def test_init(self, config, expected_runner_calls, mock_ansible_runner):
|
||||||
|
@ -71,7 +71,7 @@ class TCPCloudManagementTestCase(test.TestCase):
|
|||||||
password=None),
|
password=None),
|
||||||
mock.call(become=None, jump_host='tcp.local', jump_user='root',
|
mock.call(become=None, jump_host='tcp.local', jump_user='root',
|
||||||
private_key_file=None, remote_user='root',
|
private_key_file=None, remote_user='root',
|
||||||
password=None))
|
password=None, serial=None))
|
||||||
), (
|
), (
|
||||||
dict(address='tcp.local', username='ubuntu',
|
dict(address='tcp.local', username='ubuntu',
|
||||||
slave_username='root', master_sudo=True,
|
slave_username='root', master_sudo=True,
|
||||||
@ -80,7 +80,7 @@ class TCPCloudManagementTestCase(test.TestCase):
|
|||||||
remote_user='ubuntu', password=None),
|
remote_user='ubuntu', password=None),
|
||||||
mock.call(become=None, jump_host='tcp.local', jump_user='ubuntu',
|
mock.call(become=None, jump_host='tcp.local', jump_user='ubuntu',
|
||||||
private_key_file='/path/id_rsa', remote_user='root',
|
private_key_file='/path/id_rsa', remote_user='root',
|
||||||
password=None))
|
password=None, serial=None))
|
||||||
), (
|
), (
|
||||||
dict(address='tcp.local', username='ubuntu',
|
dict(address='tcp.local', username='ubuntu',
|
||||||
slave_username='root', slave_sudo=True,
|
slave_username='root', slave_sudo=True,
|
||||||
@ -89,7 +89,7 @@ class TCPCloudManagementTestCase(test.TestCase):
|
|||||||
remote_user='ubuntu', password=None),
|
remote_user='ubuntu', password=None),
|
||||||
mock.call(become=True, jump_host='tcp.local', jump_user='ubuntu',
|
mock.call(become=True, jump_host='tcp.local', jump_user='ubuntu',
|
||||||
private_key_file='/path/id_rsa', remote_user='root',
|
private_key_file='/path/id_rsa', remote_user='root',
|
||||||
password=None))
|
password=None, serial=None))
|
||||||
), (
|
), (
|
||||||
dict(address='tcp.local', username='ubuntu',
|
dict(address='tcp.local', username='ubuntu',
|
||||||
slave_username='root', slave_sudo=True,
|
slave_username='root', slave_sudo=True,
|
||||||
@ -99,22 +99,22 @@ class TCPCloudManagementTestCase(test.TestCase):
|
|||||||
remote_user='ubuntu', password=None),
|
remote_user='ubuntu', password=None),
|
||||||
mock.call(become=True, jump_host=None, jump_user=None,
|
mock.call(become=True, jump_host=None, jump_user=None,
|
||||||
private_key_file='/path/id_rsa', remote_user='root',
|
private_key_file='/path/id_rsa', remote_user='root',
|
||||||
password=None))
|
password=None, serial=None))
|
||||||
), (
|
), (
|
||||||
dict(address='tcp.local', username='root', password='root_pass'),
|
dict(address='tcp.local', username='root', password='root_pass'),
|
||||||
(mock.call(become=None, private_key_file=None, remote_user='root',
|
(mock.call(become=None, private_key_file=None, remote_user='root',
|
||||||
password='root_pass'),
|
password='root_pass'),
|
||||||
mock.call(become=None, jump_host='tcp.local', jump_user='root',
|
mock.call(become=None, jump_host='tcp.local', jump_user='root',
|
||||||
private_key_file=None, remote_user='root',
|
private_key_file=None, remote_user='root',
|
||||||
password='root_pass'))
|
password='root_pass', serial=None))
|
||||||
), (
|
), (
|
||||||
dict(address='tcp.local', username='root',
|
dict(address='tcp.local', username='root',
|
||||||
slave_password='slave_pass'),
|
slave_password='slave_pass', serial=42),
|
||||||
(mock.call(become=None, private_key_file=None, remote_user='root',
|
(mock.call(become=None, private_key_file=None, remote_user='root',
|
||||||
password=None),
|
password=None),
|
||||||
mock.call(become=None, jump_host='tcp.local', jump_user='root',
|
mock.call(become=None, jump_host='tcp.local', jump_user='root',
|
||||||
private_key_file=None, remote_user='root',
|
private_key_file=None, remote_user='root',
|
||||||
password='slave_pass'))
|
password='slave_pass', serial=42))
|
||||||
))
|
))
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test_init(self, config, expected_runner_calls, mock_ansible_runner):
|
def test_init(self, config, expected_runner_calls, mock_ansible_runner):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user