Refactored ESXCLI-based functions to accept a list of esxi_hosts

Previously, only one esxi_host could be passed in when connecting
to a vCenter server. This brings feature-partiy for ESXCLI-based
functions with pyVmomo-based functions, which already accept and
handle a list of hosts.

State functions were also updated.

Also fixes a bug with the ESXCLI which check in salt.utils.vmware
and provides default protocol and port options if none are provided.
This commit is contained in:
rallytime 2015-12-08 17:09:13 -07:00
parent d8b1ba3991
commit 469648dd07
3 changed files with 477 additions and 209 deletions

View file

@ -62,7 +62,7 @@ def __virtual__():
return __virtualname__
def get_coredump_network_config(host, username, password, protocol=None, port=None, esxi_host=None):
def get_coredump_network_config(host, username, password, protocol=None, port=None, esxi_hosts=None):
'''
Retrieve information on ESXi or vCenter network dump collection and
format it into a dictionary.
@ -84,13 +84,13 @@ def get_coredump_network_config(host, username, password, protocol=None, port=No
Optionally set to alternate port if the host is not using the default
port. Default port is ``443``.
esxi_host
If `host` is a vCenter host, then esxi_host is the ESXi machine on
which to execute this command.
esxi_hosts
If ``host`` is a vCenter host, then use esxi_hosts to execute this function
on a list of one or more ESXi machines.
:return: A dictionary with the network configuration, or, if getting
the network config failed, a standard cmd.run_all dictionary.
This dictionary will at least have a `retcode` key.
the network config failed, a an error message retrieved from the
standard cmd.run_all dictionary, per host.
CLI Example:
@ -101,45 +101,43 @@ def get_coredump_network_config(host, username, password, protocol=None, port=No
# Used for connecting to a vCenter Server
salt '*' vsphere.get_coredump_network_config my.vcenter.location root bad-password \
esxi_host='esxi-1.host.com'
esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
'''
cmd = 'system coredump network get'
ret = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port,
esxi_host=esxi_host)
ret = {}
if esxi_hosts:
if not isinstance(esxi_hosts, list):
raise CommandExecutionError('\'esxi_hosts\' must be a list.')
if ret['retcode'] != 0:
return ret
ret_dict = {}
for line in ret['stdout'].splitlines():
line = line.strip().lower()
if line.startswith('enabled:'):
enabled = line.split(':')
if 'true' in enabled[1]:
ret_dict['enabled'] = True
for esxi_host in esxi_hosts:
response = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port,
esxi_host=esxi_host)
if response['retcode'] != 0:
ret.update({esxi_host: {'Error': response.get('stdout')}})
else:
ret_dict['enabled'] = False
break
if line.startswith('host vnic:'):
host_vnic = line.split(':')
ret_dict['host_vnic'] = host_vnic[1].strip()
if line.startswith('network server ip:'):
ip = line.split(':')
ret_dict['ip'] = ip[1].strip()
if line.startswith('network server port:'):
ip_port = line.split(':')
ret_dict['port'] = ip_port[1].strip()
# format the response stdout into something useful
ret.update({esxi_host: {'Coredump Config': _format_coredump_stdout(response)}})
else:
# Handles a single host or a vCenter connection when no esxi_hosts are provided.
response = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port)
if response['retcode'] != 0:
ret.update({host: {'Error': response.get('stdout')}})
else:
# format the response stdout into something useful
stdout = _format_coredump_stdout(response)
ret.update({host: {'Coredump Config': stdout}})
return ret_dict
return ret
def coredump_network_enable(host, username, password, enabled, protocol=None, port=None, esxi_host=None):
def coredump_network_enable(host, username, password, enabled, protocol=None, port=None, esxi_hosts=None):
'''
Enable or disable ESXi core dump collection.
Enable or disable ESXi core dump collection. Returns ``True`` if coredump is enabled
and returns ``False`` if core dump is not enabled. If there was an error, the error
will be the value printed in the ``Error`` key dictionary for the given host.
host
The location of the host.
@ -161,13 +159,9 @@ def coredump_network_enable(host, username, password, enabled, protocol=None, po
Optionally set to alternate port if the host is not using the default
port. Default port is ``443``.
esxi_host
If `host` is a vCenter host, then esxi_host is the ESXi machine on which to
execute this command.
:return: A standard cmd.run_all dictionary. This dictionary will at least
have a `retcode` key. If `retcode` is 0 the command was
successful.
esxi_hosts
If ``host`` is a vCenter host, then use esxi_hosts to execute this function
on a list of one or more ESXi machines.
CLI Example:
@ -178,19 +172,38 @@ def coredump_network_enable(host, username, password, enabled, protocol=None, po
# Used for connecting to a vCenter Server
salt '*' vsphere.coredump_network_enable my.vcenter.location root bad-password True \
esxi_host='esxi-1.host.com'
esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
'''
if enabled:
enable_it = 1
else:
enable_it = 0
cmd = 'system coredump network set -e {0}'.format(enable_it)
return salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port,
esxi_host=esxi_host)
ret = {}
if esxi_hosts:
if not isinstance(esxi_hosts, list):
raise CommandExecutionError('\'esxi_hosts\' must be a list.')
for esxi_host in esxi_hosts:
response = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port,
esxi_host=esxi_host)
if response['retcode'] != 0:
ret.update({esxi_host: {'Error': response.get('stdout')}})
else:
ret.update({esxi_host: {'Coredump Enabled': enabled}})
else:
# Handles a single host or a vCenter connection when no esxi_hosts are provided.
response = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port)
if response['retcode'] != 0:
ret.update({host: {'Error': response.get('stdout')}})
else:
ret.update({host: {'Coredump Enabled': enabled}})
return ret
def set_coredump_network_config(host,
@ -201,7 +214,7 @@ def set_coredump_network_config(host,
port=None,
host_vnic='vmk0',
dump_port=6500,
esxi_host=None):
esxi_hosts=None):
'''
Set the network parameters for a network coredump collection.
@ -228,9 +241,9 @@ def set_coredump_network_config(host,
Optionally set to alternate port if the host is not using the default
port. Default port is ``443``.
esxi_host
If `host` is a vCenter host, then esxi_host is the ESXi machine on
which to execute this command.
esxi_hosts
If ``host`` is a vCenter host, then use esxi_hosts to execute this function
on a list of one or more ESXi machines.
host_vnic
Host VNic port through which to communicate. Defaults to ``vmk0``.
@ -238,7 +251,7 @@ def set_coredump_network_config(host,
dump_port
TCP port to use for the dump, defaults to ``6500``.
:return: A standard cmd.run_all dictionary with a `success` key added.
:return: A standard cmd.run_all dictionary with a `success` key added, per host.
`success` will be True if the set succeeded, False otherwise.
CLI Example:
@ -250,24 +263,41 @@ def set_coredump_network_config(host,
# Used for connecting to a vCenter Server
salt '*' vsphere.set_coredump_network_config my.vcenter.location root bad-password 'dump_ip.host.com' \
esxi_host='esxi-1.host.com'
esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
'''
cmd = 'system coredump network set -v {0} -i {1} -o {2}'.format(host_vnic,
dump_ip,
dump_port)
ret = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port,
esxi_host=esxi_host)
if ret['retcode'] != 0:
ret['success'] = False
ret = {}
if esxi_hosts:
if not isinstance(esxi_hosts, list):
raise CommandExecutionError('\'esxi_hosts\' must be a list.')
for esxi_host in esxi_hosts:
response = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port,
esxi_host=esxi_host)
if response['retcode'] != 0:
response['success'] = False
else:
response['success'] = True
# Update the cmd.run_all dictionary for each particular host.
ret.update({esxi_host: response})
else:
ret['success'] = True
# Handles a single host or a vCenter connection when no esxi_hosts are provided.
response = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port)
if response['retcode'] != 0:
response['success'] = False
else:
response['success'] = True
ret.update({host: response})
return ret
def get_firewall_status(host, username, password, protocol=None, port=None, esxi_host=None):
def get_firewall_status(host, username, password, protocol=None, port=None, esxi_hosts=None):
'''
Show status of all firewall rule sets.
@ -288,14 +318,14 @@ def get_firewall_status(host, username, password, protocol=None, port=None, esxi
Optionally set to alternate port if the host is not using the default
port. Default port is ``443``.
esxi_host
If `host` is a vCenter host, then esxi_host is the ESXi machine on
which to execute this command.
esxi_hosts
If ``host`` is a vCenter host, then use esxi_hosts to execute this function
on a list of one or more ESXi machines.
:return: Nested dictionary with two toplevel keys ``rulesets`` and ``success``
``success`` will be True or False depending on query success
``rulesets`` will list the rulesets and their statuses if ``success``
was true.
was true, per host.
CLI Example:
@ -306,26 +336,39 @@ def get_firewall_status(host, username, password, protocol=None, port=None, esxi
# Used for connecting to a vCenter Server
salt '*' vsphere.get_firewall_status my.vcenter.location root bad-password \
esxi_host='esxi-1.host.com'
esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
'''
cmd = 'network firewall ruleset list'
ret = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port,
esxi_host=esxi_host)
if ret['retcode'] != 0:
return {'success': False, 'rulesets': None}
ret_dict = {'success': True,
'rulesets': {}}
for line in ret['stdout'].splitlines():
if line.startswith('Name'):
continue
if line.startswith('---'):
continue
ruleset_status = line.split()
ret_dict['rulesets'][ruleset_status[0]] = bool(ruleset_status[1])
ret = {}
if esxi_hosts:
if not isinstance(esxi_hosts, list):
raise CommandExecutionError('\'esxi_hosts\' must be a list.')
return ret_dict
for esxi_host in esxi_hosts:
response = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port,
esxi_host=esxi_host)
if response['retcode'] != 0:
ret.update({esxi_host: {'Error': response['stdout'],
'success': False,
'rulesets': None}})
else:
# format the response stdout into something useful
ret.update({esxi_host: _format_firewall_stdout(response)})
else:
# Handles a single host or a vCenter connection when no esxi_hosts are provided.
response = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port)
if response['retcode'] != 0:
ret.update({host: {'Error': response['stdout'],
'success': False,
'rulesets': None}})
else:
# format the response stdout into something useful
ret.update({host: _format_firewall_stdout(response)})
return ret
def enable_firewall_ruleset(host,
@ -335,7 +378,7 @@ def enable_firewall_ruleset(host,
ruleset_name,
protocol=None,
port=None,
esxi_host=None):
esxi_hosts=None):
'''
Enable or disable an ESXi firewall rule set.
@ -362,11 +405,11 @@ def enable_firewall_ruleset(host,
Optionally set to alternate port if the host is not using the default
port. Default port is ``443``.
esxi_host
If `host` is a vCenter host, then esxi_host is the ESXi machine on
which to execute this command.
esxi_hosts
If ``host`` is a vCenter host, then use esxi_hosts to execute this function
on a list of one or more ESXi machines.
:return: A standard cmd.run_all dictionary
:return: A standard cmd.run_all dictionary, per host.
CLI Example:
@ -377,19 +420,32 @@ def enable_firewall_ruleset(host,
# Used for connecting to a vCenter Server
salt '*' vsphere.enable_firewall_ruleset my.vcenter.location root bad-password True 'syslog' \
esxi_host='esxi-1.host.com'
esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
'''
cmd = 'network firewall ruleset set --enabled {0} --ruleset-id={1}'.format(
ruleset_enable, ruleset_name
)
ret = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port,
esxi_host=esxi_host)
ret = {}
if esxi_hosts:
if not isinstance(esxi_hosts, list):
raise CommandExecutionError('\'esxi_hosts\' must be a list.')
for esxi_host in esxi_hosts:
response = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port,
esxi_host=esxi_host)
ret.update({esxi_host: response})
else:
# Handles a single host or a vCenter connection when no esxi_hosts are provided.
response = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port)
ret.update({host: response})
return ret
def syslog_service_reload(host, username, password, protocol=None, port=None, esxi_host=None):
def syslog_service_reload(host, username, password, protocol=None, port=None, esxi_hosts=None):
'''
Reload the syslog service so it will pick up any changes.
@ -410,9 +466,9 @@ def syslog_service_reload(host, username, password, protocol=None, port=None, es
Optionally set to alternate port if the host is not using the default
port. Default port is ``443``.
esxi_host
If `host` is a vCenter host, then esxi_host is the ESXi machine on
which to execute this command.
esxi_hosts
If ``host`` is a vCenter host, then use esxi_hosts to execute this function
on a list of one or more ESXi machines.
:return: A standard cmd.run_all dictionary. This dictionary will at least
have a `retcode` key. If `retcode` is 0 the command was successful.
@ -426,13 +482,26 @@ def syslog_service_reload(host, username, password, protocol=None, port=None, es
# Used for connecting to a vCenter Server
salt '*' vsphere.syslog_service_reload my.vcenter.location root bad-password \
esxi_host='esxi-1.host.com'
esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
'''
cmd = 'system syslog reload'
ret = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port,
esxi_host=esxi_host)
ret = {}
if esxi_hosts:
if not isinstance(esxi_hosts, list):
raise CommandExecutionError('\'esxi_hosts\' must be a list.')
for esxi_host in esxi_hosts:
response = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port,
esxi_host=esxi_host)
ret.update({esxi_host: response})
else:
# Handles a single host or a vCenter connection when no esxi_hosts are provided.
response = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port)
ret.update({host: response})
return ret
@ -445,7 +514,7 @@ def set_syslog_config(host,
port=None,
firewall=True,
reset_service=True,
esxi_host=None):
esxi_hosts=None):
'''
Set the specified syslog configuration parameter. By default, this function will
reset the syslog service after the configuration is set.
@ -487,54 +556,87 @@ def set_syslog_config(host,
reset_service
After a successful parameter set, reset the service. Defaults to ``True``.
esxi_host
If ``host`` is a vCenter server, then esxi_host is the ESXi machine on which to execute this command.
esxi_hosts
If ``host`` is a vCenter host, then use esxi_hosts to execute this function
on a list of one or more ESXi machines.
:return: Dictionary with a top-level key of 'success' which indicates
if all the parameters were reset, and individual keys
for each parameter indicating which succeeded or failed.
for each parameter indicating which succeeded or failed, per host.
CLI Example:
.. code-block:: bash
salt esxi_host vsphere.set_syslog_config 192.168.1.1 root secret \
# Used for ESXi host connection information
salt '*' vsphere.set_syslog_config my.esxi.host root bad-password \
loghost ssl://localhost:5432,tcp://10.1.0.1:1514
# Used for connecting to a vCenter Server
salt '*' vsphere.set_syslog_config my.vcenter.location root bad-password \
loghost ssl://localhost:5432,tcp://10.1.0.1:1514 \
esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
'''
ret = {}
# First, enable the syslog firewall ruleset, for each host, if needed.
if firewall and syslog_config == 'loghost':
ret = enable_firewall_ruleset(host, username, password,
ruleset_enable=True, ruleset_name='syslog',
protocol=protocol, port=port,
esxi_host=esxi_host)
if ret['retcode'] != 0:
return {'success': False, 'message': ret['stdout']}
if esxi_hosts:
if not isinstance(esxi_hosts, list):
raise CommandExecutionError('\'esxi_hosts\' must be a list.')
ret_dict = {}
valid_resets = ['logdir', 'loghost', 'default-rotate',
'default-size', 'default-timeout', 'logdir-unique']
if syslog_config not in valid_resets:
ret_dict = {'success': False, 'message': '\'{0}\' is not a valid config variable.'.format(syslog_config)}
return ret_dict
for esxi_host in esxi_hosts:
response = enable_firewall_ruleset(host, username, password,
ruleset_enable=True, ruleset_name='syslog',
protocol=protocol, port=port,
esxi_hosts=[esxi_host]).get(esxi_host)
if response['retcode'] != 0:
ret.update({esxi_host: {'enable_firewall': {'message': response['stdout'],
'success': False}}})
else:
ret.update({esxi_host: {'enable_firewall': {'success': True}}})
else:
# Handles a single host or a vCenter connection when no esxi_hosts are provided.
response = enable_firewall_ruleset(host, username, password,
ruleset_enable=True, ruleset_name='syslog',
protocol=protocol, port=port).get(host)
if response['retcode'] != 0:
ret.update({host: {'enable_firewall': {'message': response['stdout'],
'success': False}}})
else:
ret.update({host: {'enable_firewall': {'success': True}}})
cmd = 'system syslog config set --{0} {1}'.format(syslog_config, config_value)
ret = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port,
esxi_host=esxi_host)
ret_dict['success'] = ret['retcode'] == 0
if ret['retcode'] != 0:
ret_dict['message'] = ret['stdout']
# Set the config value on each esxi_host, if provided.
if esxi_hosts:
if not isinstance(esxi_hosts, list):
raise CommandExecutionError('\'esxi_hosts\' must be a list.')
if reset_service:
reset_ret = syslog_service_reload(host, username, password,
protocol=protocol, port=port,
esxi_host=esxi_host)
ret_dict['syslog_restart'] = reset_ret['retcode'] == 0
for esxi_host in esxi_hosts:
response = _set_syslog_config_helper(host, username, password, syslog_config,
config_value, protocol=protocol, port=port,
reset_service=reset_service, esxi_host=esxi_host)
# Ensure we don't overwrite any dictionary data already set
# By updating the esxi_host directly.
if ret.get(esxi_host) is None:
ret.update({esxi_host: {}})
ret[esxi_host].update(response)
return ret_dict
else:
# Handles a single host or a vCenter connection when no esxi_hosts are provided.
response = _set_syslog_config_helper(host, username, password, syslog_config,
config_value, protocol=protocol, port=port,
reset_service=reset_service)
# Ensure we don't overwrite any dictionary data already set
# By updating the host directly.
if ret.get(host) is None:
ret.update({host: {}})
ret[host].update(response)
return ret
def get_syslog_config(host, username, password, protocol=None, port=None, esxi_host=None):
def get_syslog_config(host, username, password, protocol=None, port=None, esxi_hosts=None):
'''
Retrieve the syslog configuration.
@ -555,42 +657,54 @@ def get_syslog_config(host, username, password, protocol=None, port=None, esxi_h
Optionally set to alternate port if the host is not using the default
port. Default port is ``443``.
esxi_host
If `host` is a vCenter host, then esxi_host is the ESXi machine on
which to execute this command.
esxi_hosts
If ``host`` is a vCenter host, then use esxi_hosts to execute this function
on a list of one or more ESXi machines.
:return: Dictionary with a keys and values corresponding to the
syslog configuration
:return: Dictionary with keys and values corresponding to the
syslog configuration, per host.
CLI Example:
.. code-block:: bash
salt esxi_host vsphere.get_syslog_config 192.168.1.1 root secret
# Used for ESXi host connection information
salt '*' vsphere.get_syslog_config my.esxi.host root bad-password
# Used for connecting to a vCenter Server
salt '*' vsphere.get_syslog_config my.vcenter.location root bad-password \
esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
'''
ret_dict = {}
cmd = 'system syslog config get'
ret = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port,
esxi_host=esxi_host)
ret = {}
if esxi_hosts:
if not isinstance(esxi_hosts, list):
raise CommandExecutionError('\'esxi_hosts\' must be a list.')
ret_dict['success'] = ret['retcode'] == 0
if ret['retcode'] != 0:
ret_dict['message'] = ret['stdout']
for esxi_host in esxi_hosts:
response = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port,
esxi_host=esxi_host)
# format the response stdout into something useful
ret.update({esxi_host: _format_syslog_config(response)})
else:
for line in ret['stdout'].splitlines():
line = line.strip()
cfgvars = line.split(': ')
key = cfgvars[0].strip()
value = cfgvars[1].strip()
ret_dict[key] = value
# Handles a single host or a vCenter connection when no esxi_hosts are provided.
response = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port)
# format the response stdout into something useful
ret.update({host: _format_syslog_config(response)})
return ret_dict
return ret
def reset_syslog_config(host, username, password, protocol=None, port=None, syslog_config=None,
esxi_host=None):
def reset_syslog_config(host,
username,
password,
protocol=None,
port=None,
syslog_config=None,
esxi_hosts=None):
'''
Reset the syslog service to its default settings.
@ -618,13 +732,13 @@ def reset_syslog_config(host, username, password, protocol=None, port=None, sysl
syslog_config
List of parameters to reset, or 'all' to reset everything.
esxi_host
If `host` is a vCenter host, then esxi_host is the ESXi machine on
which to execute this command.
esxi_hosts
If ``host`` is a vCenter host, then use esxi_hosts to execute this function
on a list of one or more ESXi machines.
:return: Dictionary with a top-level key of 'success' which indicates
if all the parameters were reset, and individual keys
for each parameter indicating which succeeded or failed.
for each parameter indicating which succeeded or failed, per host.
CLI Example:
@ -632,8 +746,13 @@ def reset_syslog_config(host, username, password, protocol=None, port=None, sysl
.. code-block:: bash
salt esxi_host vsphere.reset_syslog_config 192.168.1.1 root \
secret syslog_config='logdir,loghost'
# Used for ESXi host connection information
salt '*' vsphere.reset_syslog_config my.esxi.host root bad-password \
syslog_config='logdir,loghost'
# Used for connecting to a vCenter Server
salt '*' vsphere.reset_syslog_config my.vcenter.location root bad-password \
syslog_config='logdir,loghost' esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
'''
valid_resets = ['logdir', 'loghost', 'default-rotate',
'default-size', 'default-timeout', 'logdir-unique']
@ -645,28 +764,25 @@ def reset_syslog_config(host, username, password, protocol=None, port=None, sysl
else:
resets = [syslog_config]
ret_dict = {}
all_success = True
ret = {}
if esxi_hosts:
if not isinstance(esxi_hosts, list):
raise CommandExecutionError('\'esxi_hosts\' must be a list.')
for reset_param in resets:
if reset_param in valid_resets:
ret = salt.utils.vmware.esxcli(host, username, password, cmd + reset_param,
protocol=protocol, port=port,
esxi_host=esxi_host)
ret_dict[reset_param] = {}
ret_dict[reset_param]['success'] = ret['retcode'] == 0
if ret['retcode'] != 0:
all_success = False
ret_dict[reset_param]['message'] = ret['stdout']
else:
all_success = False
ret_dict[reset_param] = {}
ret_dict[reset_param]['success'] = False
ret_dict[reset_param]['message'] = 'Invalid syslog ' \
'configuration parameter'
for esxi_host in esxi_hosts:
response_dict = _reset_syslog_config_params(host, username, password,
cmd, resets, valid_resets,
protocol=protocol, port=port,
esxi_host=esxi_host)
ret.update({esxi_host: response_dict})
else:
# Handles a single host or a vCenter connection when no esxi_hosts are provided.
response_dict = _reset_syslog_config_params(host, username, password,
cmd, resets, valid_resets,
protocol=protocol, port=port)
ret.update({host: response_dict})
ret_dict['success'] = all_success
return ret_dict
return ret
def upload_ssh_key(host, username, password, ssh_key=None, ssh_key_file=None,
@ -2886,6 +3002,78 @@ def _check_hosts(service_instance, host, host_names):
return host_names
def _format_coredump_stdout(cmd_ret):
'''
Helper function to format the stdout from the get_coredump_network_config function.
cmd_ret
The return dictionary that comes from a cmd.run_all call.
'''
ret_dict = {}
for line in cmd_ret['stdout'].splitlines():
line = line.strip().lower()
if line.startswith('enabled:'):
enabled = line.split(':')
if 'true' in enabled[1]:
ret_dict['enabled'] = True
else:
ret_dict['enabled'] = False
break
if line.startswith('host vnic:'):
host_vnic = line.split(':')
ret_dict['host_vnic'] = host_vnic[1].strip()
if line.startswith('network server ip:'):
ip = line.split(':')
ret_dict['ip'] = ip[1].strip()
if line.startswith('network server port:'):
ip_port = line.split(':')
ret_dict['port'] = ip_port[1].strip()
return ret_dict
def _format_firewall_stdout(cmd_ret):
'''
Helper function to format the stdout from the get_firewall_status function.
cmd_ret
The return dictionary that comes from a cmd.run_all call.
'''
ret_dict = {'success': True,
'rulesets': {}}
for line in cmd_ret['stdout'].splitlines():
if line.startswith('Name'):
continue
if line.startswith('---'):
continue
ruleset_status = line.split()
ret_dict['rulesets'][ruleset_status[0]] = bool(ruleset_status[1])
return ret_dict
def _format_syslog_config(cmd_ret):
'''
Helper function to format the stdout from the get_syslog_config function.
cmd_ret
The return dictionary that comes from a cmd.run_all call.
'''
ret_dict = {'success': cmd_ret['retcode'] == 0}
if cmd_ret['retcode'] != 0:
ret_dict['message'] = cmd_ret['stdout']
else:
for line in cmd_ret['stdout'].splitlines():
line = line.strip()
cfgvars = line.split(': ')
key = cfgvars[0].strip()
value = cfgvars[1].strip()
ret_dict[key] = value
return ret_dict
def _get_date_time_mgr(host_reference):
'''
Helper function that returns a dateTimeManager object
@ -3012,3 +3200,73 @@ def _get_vsan_eligible_disks(service_instance, host, host_names):
ret.update({host_name: {'Eligible': matching}})
return ret
def _reset_syslog_config_params(host, username, password, cmd, resets, valid_resets,
protocol=None, port=None, esxi_host=None):
'''
Helper function for reset_syslog_config that resets the config and populates the return dictionary.
'''
ret_dict = {}
all_success = True
for reset_param in resets:
if reset_param in valid_resets:
ret = salt.utils.vmware.esxcli(host, username, password, cmd + reset_param,
protocol=protocol, port=port,
esxi_host=esxi_host)
ret_dict[reset_param] = {}
ret_dict[reset_param]['success'] = ret['retcode'] == 0
if ret['retcode'] != 0:
all_success = False
ret_dict[reset_param]['message'] = ret['stdout']
else:
all_success = False
ret_dict[reset_param] = {}
ret_dict[reset_param]['success'] = False
ret_dict[reset_param]['message'] = 'Invalid syslog ' \
'configuration parameter'
ret_dict['success'] = all_success
return ret_dict
def _set_syslog_config_helper(host, username, password, syslog_config, config_value,
protocol=None, port=None, reset_service=None, esxi_host=None):
'''
Helper function for set_syslog_config that sets the config and populates the return dictionary.
'''
cmd = 'system syslog config set --{0} {1}'.format(syslog_config, config_value)
ret_dict = {}
valid_resets = ['logdir', 'loghost', 'default-rotate',
'default-size', 'default-timeout', 'logdir-unique']
if syslog_config not in valid_resets:
return ret_dict.update({'success': False,
'message': '\'{0}\' is not a valid config variable.'.format(syslog_config)})
response = salt.utils.vmware.esxcli(host, username, password, cmd,
protocol=protocol, port=port,
esxi_host=esxi_host)
# Update the return dictionary for success or error messages.
if response['retcode'] != 0:
ret_dict.update({syslog_config: {'success': False,
'message': response['stdout']}})
else:
ret_dict.update({syslog_config: {'success': True}})
# Restart syslog for each host, if desired.
if reset_service:
if esxi_host:
host_name = esxi_host
esxi_host = [esxi_host]
else:
host_name = host
response = syslog_service_reload(host, username, password,
protocol=protocol, port=port,
esxi_hosts=esxi_host).get(host_name)
ret_dict[host_name].update({'syslog_restart': {'success': response['retcode'] == 0}})
return ret_dict

View file

@ -32,7 +32,6 @@ import logging
# Import Salt Libs
import salt.utils
import salt.ext.six as six
from salt.exceptions import CommandExecutionError
# Get Logging Started
@ -91,24 +90,27 @@ def coredump_configured(name, enabled, dump_ip, host_vnic='vmk0', dump_port=6500
esxi_cmd = 'esxi.cmd'
enabled_msg = 'ESXi requires that the core dump must be enabled ' \
'before any other parameters may be set.'
host = __pillar__['proxy']['host']
current_config = __salt__[esxi_cmd]('get_coredump_network_config')
if isinstance(current_config, six.string_types):
ret['comment'] = 'Error: {0}'.format(current_config)
current_config = __salt__[esxi_cmd]('get_coredump_network_config').get(host)
error = current_config.get('Error')
if error:
ret['comment'] = 'Error: {0}'.format(error)
return ret
elif ret.get('stderr'):
ret['comment'] = 'Error: {0}'.format(ret.get('stderr'))
return ret
else:
current_enabled = current_config.get('enabled')
current_config = current_config.get('Coredump Config')
current_enabled = current_config.get('enabled')
# Configure coredump enabled state, if there are changes.
if current_enabled != enabled:
enabled_changes = {'enabled': {'old': current_enabled, 'new': enabled}}
# Only run the command if not using test=True
if not __opts__['test']:
response = __salt__[esxi_cmd]('coredump_network_enable',
enabled=enabled)
if response['retcode'] != 0:
ret['comment'] = 'Error: {0}'.format(ret['stderr'])
enabled=enabled).get(host)
error = response.get('Error')
if error:
ret['comment'] = 'Error: {0}'.format(error)
return ret
# Allow users to disable core dump, but then return since
@ -116,11 +118,10 @@ def coredump_configured(name, enabled, dump_ip, host_vnic='vmk0', dump_port=6500
if not enabled:
ret['result'] = True
ret['comment'] = enabled_msg
ret['changes'].update(enabled_changes)
return ret
ret['changes'].update({'enabled':
{'old': current_enabled,
'new': enabled}})
ret['changes'].update(enabled_changes)
elif not enabled:
# If current_enabled and enabled match, but are both False,
@ -130,6 +131,8 @@ def coredump_configured(name, enabled, dump_ip, host_vnic='vmk0', dump_port=6500
ret['comment'] = enabled_msg
return ret
# Test for changes with all remaining configurations. The changes flag is used
# To detect changes, and then set_coredump_network_config is called one time.
changes = False
current_ip = current_config.get('ip')
if current_ip != dump_ip:
@ -157,7 +160,7 @@ def coredump_configured(name, enabled, dump_ip, host_vnic='vmk0', dump_port=6500
response = __salt__[esxi_cmd]('set_coredump_network_config',
dump_ip=dump_ip,
host_vnic=host_vnic,
dump_port=dump_port)
dump_port=dump_port).get(host)
if response.get('success') is False:
msg = response.get('stderr')
if not msg:
@ -815,6 +818,7 @@ def syslog_configured(name,
'changes': {},
'comment': ''}
esxi_cmd = 'esxi.cmd'
host = __pillar__['proxy']['host']
if reset_syslog_config:
if not reset_configs:
@ -822,7 +826,7 @@ def syslog_configured(name,
# Only run the command if not using test=True
if not __opts__['test']:
reset = __salt__[esxi_cmd]('reset_syslog_config',
syslog_config=reset_configs)
syslog_config=reset_configs).get(host)
for key, val in reset.iteritems():
if isinstance(val, bool):
continue
@ -838,10 +842,10 @@ def syslog_configured(name,
{'old': '',
'new': reset_configs}})
current_firewall = __salt__[esxi_cmd]('get_firewall_status')
if not current_firewall.get('success'):
ret['comment'] = 'There was an error obtaining firewall statuses. ' \
'Please check debug logs.'
current_firewall = __salt__[esxi_cmd]('get_firewall_status').get(host)
error = current_firewall.get('Error')
if error:
ret['comment'] = 'Error: {0}'.format(error)
return ret
current_firewall = current_firewall.get('rulesets').get('syslog')
@ -850,7 +854,7 @@ def syslog_configured(name,
if not __opts__['test']:
enabled = __salt__[esxi_cmd]('enable_firewall_ruleset',
ruleset_enable=firewall,
ruleset_name='syslog')
ruleset_name='syslog').get(host)
if enabled.get('retcode') != 0:
err = enabled.get('stderr')
out = enabled.get('stdout')
@ -861,7 +865,7 @@ def syslog_configured(name,
{'old': current_firewall,
'new': firewall}})
current_syslog_config = __salt__[esxi_cmd]('get_syslog_config')
current_syslog_config = __salt__[esxi_cmd]('get_syslog_config').get(host)
for key, val in syslog_configs.iteritems():
# The output of get_syslog_config has different keys than the keys
# Used to set syslog_config values. We need to look them up first.
@ -872,17 +876,17 @@ def syslog_configured(name,
return ret
current_val = current_syslog_config[lookup_key]
if current_val != val:
if str(current_val) != str(val):
# Only run the command if not using test=True
if not __opts__['test']:
response = __salt__[esxi_cmd]('set_syslog_config',
syslog_config=key,
config_value=val,
firewall=firewall,
reset_service=reset_service)
success = response.get('success')
reset_service=reset_service).get(host)
success = response.get(key).get('success')
if not success:
msg = response.get('message')
msg = response.get(key).get('message')
if not msg:
msg = 'There was an error setting syslog config \'{0}\'. ' \
'Please check debug logs.'.format(key)

View file

@ -65,11 +65,17 @@ def esxcli(host, user, pwd, cmd, protocol=None, port=None, esxi_host=None):
:return: Dictionary
'''
esx_cmd = salt.utils.which('esxicli')
esx_cmd = salt.utils.which('esxcli')
if not esx_cmd:
log.error('Missing dependency: The salt.utils.vmware.esxcli function requires ESXCLI.')
return False
# Set default port and protocol if none are provided.
if port is None:
port = 443
if protocol is None:
protocol = 'https'
if not esxi_host:
# Then we are connecting directly to an ESXi server,
# 'host' points at that server, and esxi_host is a reference to the