PageRenderTime 63ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/salt/modules/vsphere.py

https://bitbucket.org/bhuvanchandradv/salt
Python | 4206 lines | 3448 code | 158 blank | 600 comment | 173 complexity | 15c137cf6ced75e692d988162a92f3ee MD5 | raw file
Possible License(s): Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. # -*- coding: utf-8 -*-
  2. '''
  3. Manage VMware vCenter servers and ESXi hosts.
  4. .. versionadded:: 2015.8.4
  5. :codeauthor: :email:`Alexandru Bleotu <alexandru.bleotu@morganstaley.com>`
  6. Dependencies
  7. ============
  8. - pyVmomi Python Module
  9. - ESXCLI
  10. pyVmomi
  11. -------
  12. PyVmomi can be installed via pip:
  13. .. code-block:: bash
  14. pip install pyVmomi
  15. .. note::
  16. Version 6.0 of pyVmomi has some problems with SSL error handling on certain
  17. versions of Python. If using version 6.0 of pyVmomi, Python 2.6,
  18. Python 2.7.9, or newer must be present. This is due to an upstream dependency
  19. in pyVmomi 6.0 that is not supported in Python versions 2.7 to 2.7.8. If the
  20. version of Python is not in the supported range, you will need to install an
  21. earlier version of pyVmomi. See `Issue #29537`_ for more information.
  22. .. _Issue #29537: https://github.com/saltstack/salt/issues/29537
  23. Based on the note above, to install an earlier version of pyVmomi than the
  24. version currently listed in PyPi, run the following:
  25. .. code-block:: bash
  26. pip install pyVmomi==5.5.0.2014.1.1
  27. The 5.5.0.2014.1.1 is a known stable version that this original vSphere Execution
  28. Module was developed against.
  29. ESXCLI
  30. ------
  31. Currently, about a third of the functions used in the vSphere Execution Module require
  32. the ESXCLI package be installed on the machine running the Proxy Minion process.
  33. The ESXCLI package is also referred to as the VMware vSphere CLI, or vCLI. VMware
  34. provides vCLI package installation instructions for `vSphere 5.5`_ and
  35. `vSphere 6.0`_.
  36. .. _vSphere 5.5: http://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.vcli.getstart.doc/cli_install.4.2.html
  37. .. _vSphere 6.0: http://pubs.vmware.com/vsphere-60/index.jsp#com.vmware.vcli.getstart.doc/cli_install.4.2.html
  38. Once all of the required dependencies are in place and the vCLI package is
  39. installed, you can check to see if you can connect to your ESXi host or vCenter
  40. server by running the following command:
  41. .. code-block:: bash
  42. esxcli -s <host-location> -u <username> -p <password> system syslog config get
  43. If the connection was successful, ESXCLI was successfully installed on your system.
  44. You should see output related to the ESXi host's syslog configuration.
  45. .. note::
  46. Be aware that some functionality in this execution module may depend on the
  47. type of license attached to a vCenter Server or ESXi host(s).
  48. For example, certain services are only available to manipulate service state
  49. or policies with a VMware vSphere Enterprise or Enterprise Plus license, while
  50. others are available with a Standard license. The ``ntpd`` service is restricted
  51. to an Enterprise Plus license, while ``ssh`` is available via the Standard
  52. license.
  53. Please see the `vSphere Comparison`_ page for more information.
  54. .. _vSphere Comparison: https://www.vmware.com/products/vsphere/compare
  55. About
  56. =====
  57. This execution module was designed to be able to handle connections both to a
  58. vCenter Server, as well as to an ESXi host. It utilizes the pyVmomi Python
  59. library and the ESXCLI package to run remote execution functions against either
  60. the defined vCenter server or the ESXi host.
  61. Whether or not the function runs against a vCenter Server or an ESXi host depends
  62. entirely upon the arguments passed into the function. Each function requires a
  63. ``host`` location, ``username``, and ``password``. If the credentials provided
  64. apply to a vCenter Server, then the function will be run against the vCenter
  65. Server. For example, when listing hosts using vCenter credentials, you'll get a
  66. list of hosts associated with that vCenter Server:
  67. .. code-block:: bash
  68. # salt my-minion vsphere.list_hosts <vcenter-ip> <vcenter-user> <vcenter-password>
  69. my-minion:
  70. - esxi-1.example.com
  71. - esxi-2.example.com
  72. However, some functions should be used against ESXi hosts, not vCenter Servers.
  73. Functionality such as getting a host's coredump network configuration should be
  74. performed against a host and not a vCenter server. If the authentication information
  75. you're using is against a vCenter server and not an ESXi host, you can provide the
  76. host name that is associated with the vCenter server in the command, as a list, using
  77. the ``host_names`` or ``esxi_host`` kwarg. For example:
  78. .. code-block:: bash
  79. # salt my-minion vsphere.get_coredump_network_config <vcenter-ip> <vcenter-user> \
  80. <vcenter-password> esxi_hosts='[esxi-1.example.com, esxi-2.example.com]'
  81. my-minion:
  82. ----------
  83. esxi-1.example.com:
  84. ----------
  85. Coredump Config:
  86. ----------
  87. enabled:
  88. False
  89. esxi-2.example.com:
  90. ----------
  91. Coredump Config:
  92. ----------
  93. enabled:
  94. True
  95. host_vnic:
  96. vmk0
  97. ip:
  98. coredump-location.example.com
  99. port:
  100. 6500
  101. You can also use these functions against an ESXi host directly by establishing a
  102. connection to an ESXi host using the host's location, username, and password. If ESXi
  103. connection credentials are used instead of vCenter credentials, the ``host_names`` and
  104. ``esxi_hosts`` arguments are not needed.
  105. .. code-block:: bash
  106. # salt my-minion vsphere.get_coredump_network_config esxi-1.example.com root <host-password>
  107. local:
  108. ----------
  109. 10.4.28.150:
  110. ----------
  111. Coredump Config:
  112. ----------
  113. enabled:
  114. True
  115. host_vnic:
  116. vmk0
  117. ip:
  118. coredump-location.example.com
  119. port:
  120. 6500
  121. '''
  122. # Import Python Libs
  123. from __future__ import absolute_import
  124. import datetime
  125. import logging
  126. import sys
  127. import inspect
  128. from functools import wraps
  129. # Import Salt Libs
  130. import salt.ext.six as six
  131. import salt.utils
  132. import salt.utils.vmware
  133. import salt.utils.http
  134. from salt.utils import dictupdate
  135. from salt.exceptions import CommandExecutionError, VMwareSaltError
  136. from salt.utils.decorators import depends, ignores_kwargs
  137. from salt.utils import clean_kwargs
  138. # Import Third Party Libs
  139. try:
  140. from pyVmomi import vim, vmodl
  141. HAS_PYVMOMI = True
  142. except ImportError:
  143. HAS_PYVMOMI = False
  144. esx_cli = salt.utils.which('esxcli')
  145. if esx_cli:
  146. HAS_ESX_CLI = True
  147. else:
  148. HAS_ESX_CLI = False
  149. log = logging.getLogger(__name__)
  150. __virtualname__ = 'vsphere'
  151. __proxyenabled__ = ['esxi']
  152. def __virtual__():
  153. return __virtualname__
  154. def get_proxy_type():
  155. '''
  156. Returns the proxy type
  157. CLI Example:
  158. .. code-block:: bash
  159. salt '*' vsphere.get_proxy_type
  160. '''
  161. return __pillar__['proxy']['proxytype']
  162. def _get_proxy_connection_details():
  163. '''
  164. Returns the connection details of the following proxies: esxi
  165. '''
  166. proxytype = get_proxy_type()
  167. if proxytype == 'esxi':
  168. details = __salt__['esxi.get_details']()
  169. else:
  170. raise CommandExecutionError('\'{0}\' proxy is not supported'
  171. ''.format(proxytype))
  172. return \
  173. details.get('vcenter') if 'vcenter' in details \
  174. else details.get('host'), \
  175. details.get('username'), \
  176. details.get('password'), details.get('protocol'), \
  177. details.get('port'), details.get('mechanism'), \
  178. details.get('principal'), details.get('domain')
  179. def supports_proxies(*proxy_types):
  180. '''
  181. Decorator to specify which proxy types are supported by a function
  182. proxy_types:
  183. Arbitrary list of strings with the supported types of proxies
  184. '''
  185. def _supports_proxies(fn):
  186. def __supports_proxies(*args, **kwargs):
  187. proxy_type = get_proxy_type()
  188. if proxy_type not in proxy_types:
  189. raise CommandExecutionError(
  190. '\'{0}\' proxy is not supported by function {1}'
  191. ''.format(proxy_type, fn.__name__))
  192. return fn(*args, **clean_kwargs(**kwargs))
  193. return __supports_proxies
  194. return _supports_proxies
  195. def gets_service_instance_via_proxy(fn):
  196. '''
  197. Decorator that connects to a target system (vCenter or ESXi host) using the
  198. proxy details and passes the connection (vim.ServiceInstance) to
  199. the decorated function.
  200. Notes:
  201. 1. The decorated function must have a ``service_instance`` parameter
  202. or a ``**kwarg`` type argument (name of argument is not important);
  203. 2. If the ``service_instance`` parameter is already defined, the value
  204. is passed through to the decorated function;
  205. 3. If the ``service_instance`` parameter in not defined, the
  206. connection is created using the proxy details and the service instance
  207. is returned.
  208. CLI Example:
  209. None, this is a decorator
  210. '''
  211. fn_name = fn.__name__
  212. try:
  213. arg_names, args_name, kwargs_name, default_values, _, _, _ = \
  214. inspect.getfullargspec(fn)
  215. except AttributeError:
  216. # Fallback to Python 2.7
  217. arg_names, args_name, kwargs_name, default_values = \
  218. inspect.getargspec(fn)
  219. default_values = default_values if default_values is not None else []
  220. @wraps(fn)
  221. def _gets_service_instance_via_proxy(*args, **kwargs):
  222. if 'service_instance' not in arg_names and not kwargs_name:
  223. raise CommandExecutionError(
  224. 'Function {0} must have either a \'service_instance\', or a '
  225. '\'**kwargs\' type parameter'.format(fn_name))
  226. connection_details = _get_proxy_connection_details()
  227. # Figure out how to pass in the connection value
  228. local_service_instance = None
  229. if 'service_instance' in arg_names:
  230. idx = arg_names.index('service_instance')
  231. if idx >= len(arg_names) - len(default_values):
  232. # 'service_instance' has a default value:
  233. # we check if we need to instantiate it or
  234. # pass it through
  235. #
  236. # NOTE: if 'service_instance' doesn't have a default value
  237. # it must be explicitly set in the function call so we pass it
  238. # through
  239. # There are two cases:
  240. # 1. service_instance was passed in as a positional parameter
  241. # 2. service_instance was passed in as a named paramter
  242. if len(args) > idx:
  243. # case 1: The call was made with enough positional
  244. # parameters to include 'service_instance'
  245. if not args[idx]:
  246. local_service_instance = \
  247. salt.utils.vmware.get_service_instance(
  248. *connection_details)
  249. args[idx] = local_service_instance
  250. else:
  251. # case 2: Not enough positional parameters so
  252. # 'service_instance' must be a named parameter
  253. if not kwargs.get('service_instance'):
  254. local_service_instance = \
  255. salt.utils.vmware.get_service_instance(
  256. *connection_details)
  257. kwargs['service_instance'] = local_service_instance
  258. else:
  259. # 'service_instance' is not a paremter in the function definition
  260. # but it will be caught by the **kwargs parameter
  261. if not kwargs.get('service_instance'):
  262. local_service_instance = \
  263. salt.utils.vmware.get_service_instance(
  264. *connection_details)
  265. kwargs['service_instance'] = local_service_instance
  266. try:
  267. ret = fn(*args, **clean_kwargs(**kwargs))
  268. # Disconnect if connected in the decorator
  269. if local_service_instance:
  270. salt.utils.vmware.disconnect(local_service_instance)
  271. return ret
  272. except Exception as e:
  273. # Disconnect if connected in the decorator
  274. if local_service_instance:
  275. salt.utils.vmware.disconnect(local_service_instance)
  276. # raise original exception and traceback
  277. six.reraise(*sys.exc_info())
  278. return _gets_service_instance_via_proxy
  279. @supports_proxies('esxi')
  280. def get_service_instance_via_proxy(service_instance=None):
  281. '''
  282. Returns a service instance to the proxied endpoint (vCenter/ESXi host).
  283. Note:
  284. Should be used by state functions not invoked directly.
  285. CLI Example:
  286. See note above
  287. '''
  288. connection_details = _get_proxy_connection_details()
  289. return salt.utils.vmware.get_service_instance(*connection_details)
  290. @supports_proxies('esxi')
  291. def disconnect(service_instance):
  292. '''
  293. Disconnects from a vCenter or ESXi host
  294. Note:
  295. Should be used by state functions, not invoked directly.
  296. service_instance
  297. Service instance (vim.ServiceInstance)
  298. CLI Example:
  299. See note above.
  300. '''
  301. salt.utils.vmware.disconnect(service_instance)
  302. return True
  303. @depends(HAS_ESX_CLI)
  304. def esxcli_cmd(cmd_str, host=None, username=None, password=None, protocol=None, port=None, esxi_hosts=None, credstore=None):
  305. '''
  306. Run an ESXCLI command directly on the host or list of hosts.
  307. host
  308. The location of the host.
  309. username
  310. The username used to login to the host, such as ``root``.
  311. password
  312. The password used to login to the host.
  313. cmd_str
  314. The ESXCLI command to run. Note: This should not include the ``-s``, ``-u``,
  315. ``-p``, ``-h``, ``--protocol``, or ``--portnumber`` arguments that are
  316. frequently passed when using a bare ESXCLI command from the command line.
  317. Those arguments are handled by this function via the other args and kwargs.
  318. protocol
  319. Optionally set to alternate protocol if the host is not using the default
  320. protocol. Default protocol is ``https``.
  321. port
  322. Optionally set to alternate port if the host is not using the default
  323. port. Default port is ``443``.
  324. esxi_hosts
  325. If ``host`` is a vCenter host, then use esxi_hosts to execute this function
  326. on a list of one or more ESXi machines.
  327. credstore
  328. Optionally set to path to the credential store file.
  329. CLI Example:
  330. .. code-block:: bash
  331. # Used for ESXi host connection information
  332. salt '*' vsphere.esxcli_cmd my.esxi.host root bad-password \
  333. 'system coredump network get'
  334. # Used for connecting to a vCenter Server
  335. salt '*' vsphere.esxcli_cmd my.vcenter.location root bad-password \
  336. 'system coredump network get' esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
  337. '''
  338. ret = {}
  339. if esxi_hosts:
  340. if not isinstance(esxi_hosts, list):
  341. raise CommandExecutionError('\'esxi_hosts\' must be a list.')
  342. for esxi_host in esxi_hosts:
  343. response = salt.utils.vmware.esxcli(host, username, password, cmd_str,
  344. protocol=protocol, port=port,
  345. esxi_host=esxi_host, credstore=credstore)
  346. if response['retcode'] != 0:
  347. ret.update({esxi_host: {'Error': response.get('stdout')}})
  348. else:
  349. ret.update({esxi_host: response})
  350. else:
  351. # Handles a single host or a vCenter connection when no esxi_hosts are provided.
  352. response = salt.utils.vmware.esxcli(host, username, password, cmd_str,
  353. protocol=protocol, port=port,
  354. credstore=credstore)
  355. if response['retcode'] != 0:
  356. ret.update({host: {'Error': response.get('stdout')}})
  357. else:
  358. ret.update({host: response})
  359. return ret
  360. @depends(HAS_ESX_CLI)
  361. def get_coredump_network_config(host, username, password, protocol=None, port=None, esxi_hosts=None, credstore=None):
  362. '''
  363. Retrieve information on ESXi or vCenter network dump collection and
  364. format it into a dictionary.
  365. host
  366. The location of the host.
  367. username
  368. The username used to login to the host, such as ``root``.
  369. password
  370. The password used to login to the host.
  371. protocol
  372. Optionally set to alternate protocol if the host is not using the default
  373. protocol. Default protocol is ``https``.
  374. port
  375. Optionally set to alternate port if the host is not using the default
  376. port. Default port is ``443``.
  377. esxi_hosts
  378. If ``host`` is a vCenter host, then use esxi_hosts to execute this function
  379. on a list of one or more ESXi machines.
  380. credstore
  381. Optionally set to path to the credential store file.
  382. :return: A dictionary with the network configuration, or, if getting
  383. the network config failed, a an error message retrieved from the
  384. standard cmd.run_all dictionary, per host.
  385. CLI Example:
  386. .. code-block:: bash
  387. # Used for ESXi host connection information
  388. salt '*' vsphere.get_coredump_network_config my.esxi.host root bad-password
  389. # Used for connecting to a vCenter Server
  390. salt '*' vsphere.get_coredump_network_config my.vcenter.location root bad-password \
  391. esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
  392. '''
  393. cmd = 'system coredump network get'
  394. ret = {}
  395. if esxi_hosts:
  396. if not isinstance(esxi_hosts, list):
  397. raise CommandExecutionError('\'esxi_hosts\' must be a list.')
  398. for esxi_host in esxi_hosts:
  399. response = salt.utils.vmware.esxcli(host, username, password, cmd,
  400. protocol=protocol, port=port,
  401. esxi_host=esxi_host, credstore=credstore)
  402. if response['retcode'] != 0:
  403. ret.update({esxi_host: {'Error': response.get('stdout')}})
  404. else:
  405. # format the response stdout into something useful
  406. ret.update({esxi_host: {'Coredump Config': _format_coredump_stdout(response)}})
  407. else:
  408. # Handles a single host or a vCenter connection when no esxi_hosts are provided.
  409. response = salt.utils.vmware.esxcli(host, username, password, cmd,
  410. protocol=protocol, port=port,
  411. credstore=credstore)
  412. if response['retcode'] != 0:
  413. ret.update({host: {'Error': response.get('stdout')}})
  414. else:
  415. # format the response stdout into something useful
  416. stdout = _format_coredump_stdout(response)
  417. ret.update({host: {'Coredump Config': stdout}})
  418. return ret
  419. @depends(HAS_ESX_CLI)
  420. def coredump_network_enable(host, username, password, enabled, protocol=None, port=None, esxi_hosts=None, credstore=None):
  421. '''
  422. Enable or disable ESXi core dump collection. Returns ``True`` if coredump is enabled
  423. and returns ``False`` if core dump is not enabled. If there was an error, the error
  424. will be the value printed in the ``Error`` key dictionary for the given host.
  425. host
  426. The location of the host.
  427. username
  428. The username used to login to the host, such as ``root``.
  429. password
  430. The password used to login to the host.
  431. enabled
  432. Python True or False to enable or disable coredumps.
  433. protocol
  434. Optionally set to alternate protocol if the host is not using the default
  435. protocol. Default protocol is ``https``.
  436. port
  437. Optionally set to alternate port if the host is not using the default
  438. port. Default port is ``443``.
  439. esxi_hosts
  440. If ``host`` is a vCenter host, then use esxi_hosts to execute this function
  441. on a list of one or more ESXi machines.
  442. credstore
  443. Optionally set to path to the credential store file.
  444. CLI Example:
  445. .. code-block:: bash
  446. # Used for ESXi host connection information
  447. salt '*' vsphere.coredump_network_enable my.esxi.host root bad-password True
  448. # Used for connecting to a vCenter Server
  449. salt '*' vsphere.coredump_network_enable my.vcenter.location root bad-password True \
  450. esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
  451. '''
  452. if enabled:
  453. enable_it = 1
  454. else:
  455. enable_it = 0
  456. cmd = 'system coredump network set -e {0}'.format(enable_it)
  457. ret = {}
  458. if esxi_hosts:
  459. if not isinstance(esxi_hosts, list):
  460. raise CommandExecutionError('\'esxi_hosts\' must be a list.')
  461. for esxi_host in esxi_hosts:
  462. response = salt.utils.vmware.esxcli(host, username, password, cmd,
  463. protocol=protocol, port=port,
  464. esxi_host=esxi_host, credstore=credstore)
  465. if response['retcode'] != 0:
  466. ret.update({esxi_host: {'Error': response.get('stdout')}})
  467. else:
  468. ret.update({esxi_host: {'Coredump Enabled': enabled}})
  469. else:
  470. # Handles a single host or a vCenter connection when no esxi_hosts are provided.
  471. response = salt.utils.vmware.esxcli(host, username, password, cmd,
  472. protocol=protocol, port=port,
  473. credstore=credstore)
  474. if response['retcode'] != 0:
  475. ret.update({host: {'Error': response.get('stdout')}})
  476. else:
  477. ret.update({host: {'Coredump Enabled': enabled}})
  478. return ret
  479. @depends(HAS_ESX_CLI)
  480. def set_coredump_network_config(host,
  481. username,
  482. password,
  483. dump_ip,
  484. protocol=None,
  485. port=None,
  486. host_vnic='vmk0',
  487. dump_port=6500,
  488. esxi_hosts=None,
  489. credstore=None):
  490. '''
  491. Set the network parameters for a network coredump collection.
  492. Note that ESXi requires that the dumps first be enabled (see
  493. `coredump_network_enable`) before these parameters may be set.
  494. host
  495. The location of the host.
  496. username
  497. The username used to login to the host, such as ``root``.
  498. password
  499. The password used to login to the host.
  500. dump_ip
  501. IP address of host that will accept the dump.
  502. protocol
  503. Optionally set to alternate protocol if the host is not using the default
  504. protocol. Default protocol is ``https``.
  505. port
  506. Optionally set to alternate port if the host is not using the default
  507. port. Default port is ``443``.
  508. esxi_hosts
  509. If ``host`` is a vCenter host, then use esxi_hosts to execute this function
  510. on a list of one or more ESXi machines.
  511. host_vnic
  512. Host VNic port through which to communicate. Defaults to ``vmk0``.
  513. dump_port
  514. TCP port to use for the dump, defaults to ``6500``.
  515. credstore
  516. Optionally set to path to the credential store file.
  517. :return: A standard cmd.run_all dictionary with a `success` key added, per host.
  518. `success` will be True if the set succeeded, False otherwise.
  519. CLI Example:
  520. .. code-block:: bash
  521. # Used for ESXi host connection information
  522. salt '*' vsphere.set_coredump_network_config my.esxi.host root bad-password 'dump_ip.host.com'
  523. # Used for connecting to a vCenter Server
  524. salt '*' vsphere.set_coredump_network_config my.vcenter.location root bad-password 'dump_ip.host.com' \
  525. esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
  526. '''
  527. cmd = 'system coredump network set -v {0} -i {1} -o {2}'.format(host_vnic,
  528. dump_ip,
  529. dump_port)
  530. ret = {}
  531. if esxi_hosts:
  532. if not isinstance(esxi_hosts, list):
  533. raise CommandExecutionError('\'esxi_hosts\' must be a list.')
  534. for esxi_host in esxi_hosts:
  535. response = salt.utils.vmware.esxcli(host, username, password, cmd,
  536. protocol=protocol, port=port,
  537. esxi_host=esxi_host, credstore=credstore)
  538. if response['retcode'] != 0:
  539. response['success'] = False
  540. else:
  541. response['success'] = True
  542. # Update the cmd.run_all dictionary for each particular host.
  543. ret.update({esxi_host: response})
  544. else:
  545. # Handles a single host or a vCenter connection when no esxi_hosts are provided.
  546. response = salt.utils.vmware.esxcli(host, username, password, cmd,
  547. protocol=protocol, port=port,
  548. credstore=credstore)
  549. if response['retcode'] != 0:
  550. response['success'] = False
  551. else:
  552. response['success'] = True
  553. ret.update({host: response})
  554. return ret
  555. @depends(HAS_ESX_CLI)
  556. def get_firewall_status(host, username, password, protocol=None, port=None, esxi_hosts=None, credstore=None):
  557. '''
  558. Show status of all firewall rule sets.
  559. host
  560. The location of the host.
  561. username
  562. The username used to login to the host, such as ``root``.
  563. password
  564. The password used to login to the host.
  565. protocol
  566. Optionally set to alternate protocol if the host is not using the default
  567. protocol. Default protocol is ``https``.
  568. port
  569. Optionally set to alternate port if the host is not using the default
  570. port. Default port is ``443``.
  571. esxi_hosts
  572. If ``host`` is a vCenter host, then use esxi_hosts to execute this function
  573. on a list of one or more ESXi machines.
  574. credstore
  575. Optionally set to path to the credential store file.
  576. :return: Nested dictionary with two toplevel keys ``rulesets`` and ``success``
  577. ``success`` will be True or False depending on query success
  578. ``rulesets`` will list the rulesets and their statuses if ``success``
  579. was true, per host.
  580. CLI Example:
  581. .. code-block:: bash
  582. # Used for ESXi host connection information
  583. salt '*' vsphere.get_firewall_status my.esxi.host root bad-password
  584. # Used for connecting to a vCenter Server
  585. salt '*' vsphere.get_firewall_status my.vcenter.location root bad-password \
  586. esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
  587. '''
  588. cmd = 'network firewall ruleset list'
  589. ret = {}
  590. if esxi_hosts:
  591. if not isinstance(esxi_hosts, list):
  592. raise CommandExecutionError('\'esxi_hosts\' must be a list.')
  593. for esxi_host in esxi_hosts:
  594. response = salt.utils.vmware.esxcli(host, username, password, cmd,
  595. protocol=protocol, port=port,
  596. esxi_host=esxi_host, credstore=credstore)
  597. if response['retcode'] != 0:
  598. ret.update({esxi_host: {'Error': response['stdout'],
  599. 'success': False,
  600. 'rulesets': None}})
  601. else:
  602. # format the response stdout into something useful
  603. ret.update({esxi_host: _format_firewall_stdout(response)})
  604. else:
  605. # Handles a single host or a vCenter connection when no esxi_hosts are provided.
  606. response = salt.utils.vmware.esxcli(host, username, password, cmd,
  607. protocol=protocol, port=port,
  608. credstore=credstore)
  609. if response['retcode'] != 0:
  610. ret.update({host: {'Error': response['stdout'],
  611. 'success': False,
  612. 'rulesets': None}})
  613. else:
  614. # format the response stdout into something useful
  615. ret.update({host: _format_firewall_stdout(response)})
  616. return ret
  617. @depends(HAS_ESX_CLI)
  618. def enable_firewall_ruleset(host,
  619. username,
  620. password,
  621. ruleset_enable,
  622. ruleset_name,
  623. protocol=None,
  624. port=None,
  625. esxi_hosts=None,
  626. credstore=None):
  627. '''
  628. Enable or disable an ESXi firewall rule set.
  629. host
  630. The location of the host.
  631. username
  632. The username used to login to the host, such as ``root``.
  633. password
  634. The password used to login to the host.
  635. ruleset_enable
  636. True to enable the ruleset, false to disable.
  637. ruleset_name
  638. Name of ruleset to target.
  639. protocol
  640. Optionally set to alternate protocol if the host is not using the default
  641. protocol. Default protocol is ``https``.
  642. port
  643. Optionally set to alternate port if the host is not using the default
  644. port. Default port is ``443``.
  645. esxi_hosts
  646. If ``host`` is a vCenter host, then use esxi_hosts to execute this function
  647. on a list of one or more ESXi machines.
  648. credstore
  649. Optionally set to path to the credential store file.
  650. :return: A standard cmd.run_all dictionary, per host.
  651. CLI Example:
  652. .. code-block:: bash
  653. # Used for ESXi host connection information
  654. salt '*' vsphere.enable_firewall_ruleset my.esxi.host root bad-password True 'syslog'
  655. # Used for connecting to a vCenter Server
  656. salt '*' vsphere.enable_firewall_ruleset my.vcenter.location root bad-password True 'syslog' \
  657. esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
  658. '''
  659. cmd = 'network firewall ruleset set --enabled {0} --ruleset-id={1}'.format(
  660. ruleset_enable, ruleset_name
  661. )
  662. ret = {}
  663. if esxi_hosts:
  664. if not isinstance(esxi_hosts, list):
  665. raise CommandExecutionError('\'esxi_hosts\' must be a list.')
  666. for esxi_host in esxi_hosts:
  667. response = salt.utils.vmware.esxcli(host, username, password, cmd,
  668. protocol=protocol, port=port,
  669. esxi_host=esxi_host, credstore=credstore)
  670. ret.update({esxi_host: response})
  671. else:
  672. # Handles a single host or a vCenter connection when no esxi_hosts are provided.
  673. response = salt.utils.vmware.esxcli(host, username, password, cmd,
  674. protocol=protocol, port=port,
  675. credstore=credstore)
  676. ret.update({host: response})
  677. return ret
  678. @depends(HAS_ESX_CLI)
  679. def syslog_service_reload(host, username, password, protocol=None, port=None, esxi_hosts=None, credstore=None):
  680. '''
  681. Reload the syslog service so it will pick up any changes.
  682. host
  683. The location of the host.
  684. username
  685. The username used to login to the host, such as ``root``.
  686. password
  687. The password used to login to the host.
  688. protocol
  689. Optionally set to alternate protocol if the host is not using the default
  690. protocol. Default protocol is ``https``.
  691. port
  692. Optionally set to alternate port if the host is not using the default
  693. port. Default port is ``443``.
  694. esxi_hosts
  695. If ``host`` is a vCenter host, then use esxi_hosts to execute this function
  696. on a list of one or more ESXi machines.
  697. credstore
  698. Optionally set to path to the credential store file.
  699. :return: A standard cmd.run_all dictionary. This dictionary will at least
  700. have a `retcode` key. If `retcode` is 0 the command was successful.
  701. CLI Example:
  702. .. code-block:: bash
  703. # Used for ESXi host connection information
  704. salt '*' vsphere.syslog_service_reload my.esxi.host root bad-password
  705. # Used for connecting to a vCenter Server
  706. salt '*' vsphere.syslog_service_reload my.vcenter.location root bad-password \
  707. esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
  708. '''
  709. cmd = 'system syslog reload'
  710. ret = {}
  711. if esxi_hosts:
  712. if not isinstance(esxi_hosts, list):
  713. raise CommandExecutionError('\'esxi_hosts\' must be a list.')
  714. for esxi_host in esxi_hosts:
  715. response = salt.utils.vmware.esxcli(host, username, password, cmd,
  716. protocol=protocol, port=port,
  717. esxi_host=esxi_host, credstore=credstore)
  718. ret.update({esxi_host: response})
  719. else:
  720. # Handles a single host or a vCenter connection when no esxi_hosts are provided.
  721. response = salt.utils.vmware.esxcli(host, username, password, cmd,
  722. protocol=protocol, port=port,
  723. credstore=credstore)
  724. ret.update({host: response})
  725. return ret
  726. @depends(HAS_ESX_CLI)
  727. def set_syslog_config(host,
  728. username,
  729. password,
  730. syslog_config,
  731. config_value,
  732. protocol=None,
  733. port=None,
  734. firewall=True,
  735. reset_service=True,
  736. esxi_hosts=None,
  737. credstore=None):
  738. '''
  739. Set the specified syslog configuration parameter. By default, this function will
  740. reset the syslog service after the configuration is set.
  741. host
  742. ESXi or vCenter host to connect to.
  743. username
  744. User to connect as, usually root.
  745. password
  746. Password to connect with.
  747. syslog_config
  748. Name of parameter to set (corresponds to the command line switch for
  749. esxcli without the double dashes (--))
  750. Valid syslog_config values are ``logdir``, ``loghost``, ``default-rotate`,
  751. ``default-size``, ``default-timeout``, and ``logdir-unique``.
  752. config_value
  753. Value for the above parameter. For ``loghost``, URLs or IP addresses to
  754. use for logging. Multiple log servers can be specified by listing them,
  755. comma-separated, but without spaces before or after commas.
  756. (reference: https://blogs.vmware.com/vsphere/2012/04/configuring-multiple-syslog-servers-for-esxi-5.html)
  757. protocol
  758. Optionally set to alternate protocol if the host is not using the default
  759. protocol. Default protocol is ``https``.
  760. port
  761. Optionally set to alternate port if the host is not using the default
  762. port. Default port is ``443``.
  763. firewall
  764. Enable the firewall rule set for syslog. Defaults to ``True``.
  765. reset_service
  766. After a successful parameter set, reset the service. Defaults to ``True``.
  767. esxi_hosts
  768. If ``host`` is a vCenter host, then use esxi_hosts to execute this function
  769. on a list of one or more ESXi machines.
  770. credstore
  771. Optionally set to path to the credential store file.
  772. :return: Dictionary with a top-level key of 'success' which indicates
  773. if all the parameters were reset, and individual keys
  774. for each parameter indicating which succeeded or failed, per host.
  775. CLI Example:
  776. .. code-block:: bash
  777. # Used for ESXi host connection information
  778. salt '*' vsphere.set_syslog_config my.esxi.host root bad-password \
  779. loghost ssl://localhost:5432,tcp://10.1.0.1:1514
  780. # Used for connecting to a vCenter Server
  781. salt '*' vsphere.set_syslog_config my.vcenter.location root bad-password \
  782. loghost ssl://localhost:5432,tcp://10.1.0.1:1514 \
  783. esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
  784. '''
  785. ret = {}
  786. # First, enable the syslog firewall ruleset, for each host, if needed.
  787. if firewall and syslog_config == 'loghost':
  788. if esxi_hosts:
  789. if not isinstance(esxi_hosts, list):
  790. raise CommandExecutionError('\'esxi_hosts\' must be a list.')
  791. for esxi_host in esxi_hosts:
  792. response = enable_firewall_ruleset(host, username, password,
  793. ruleset_enable=True, ruleset_name='syslog',
  794. protocol=protocol, port=port,
  795. esxi_hosts=[esxi_host], credstore=credstore).get(esxi_host)
  796. if response['retcode'] != 0:
  797. ret.update({esxi_host: {'enable_firewall': {'message': response['stdout'],
  798. 'success': False}}})
  799. else:
  800. ret.update({esxi_host: {'enable_firewall': {'success': True}}})
  801. else:
  802. # Handles a single host or a vCenter connection when no esxi_hosts are provided.
  803. response = enable_firewall_ruleset(host, username, password,
  804. ruleset_enable=True, ruleset_name='syslog',
  805. protocol=protocol, port=port,
  806. credstore=credstore).get(host)
  807. if response['retcode'] != 0:
  808. ret.update({host: {'enable_firewall': {'message': response['stdout'],
  809. 'success': False}}})
  810. else:
  811. ret.update({host: {'enable_firewall': {'success': True}}})
  812. # Set the config value on each esxi_host, if provided.
  813. if esxi_hosts:
  814. if not isinstance(esxi_hosts, list):
  815. raise CommandExecutionError('\'esxi_hosts\' must be a list.')
  816. for esxi_host in esxi_hosts:
  817. response = _set_syslog_config_helper(host, username, password, syslog_config,
  818. config_value, protocol=protocol, port=port,
  819. reset_service=reset_service, esxi_host=esxi_host,
  820. credstore=credstore)
  821. # Ensure we don't overwrite any dictionary data already set
  822. # By updating the esxi_host directly.
  823. if ret.get(esxi_host) is None:
  824. ret.update({esxi_host: {}})
  825. ret[esxi_host].update(response)
  826. else:
  827. # Handles a single host or a vCenter connection when no esxi_hosts are provided.
  828. response = _set_syslog_config_helper(host, username, password, syslog_config,
  829. config_value, protocol=protocol, port=port,
  830. reset_service=reset_service, credstore=credstore)
  831. # Ensure we don't overwrite any dictionary data already set
  832. # By updating the host directly.
  833. if ret.get(host) is None:
  834. ret.update({host: {}})
  835. ret[host].update(response)
  836. return ret
  837. @depends(HAS_ESX_CLI)
  838. def get_syslog_config(host, username, password, protocol=None, port=None, esxi_hosts=None, credstore=None):
  839. '''
  840. Retrieve the syslog configuration.
  841. host
  842. The location of the host.
  843. username
  844. The username used to login to the host, such as ``root``.
  845. password
  846. The password used to login to the host.
  847. protocol
  848. Optionally set to alternate protocol if the host is not using the default
  849. protocol. Default protocol is ``https``.
  850. port
  851. Optionally set to alternate port if the host is not using the default
  852. port. Default port is ``443``.
  853. esxi_hosts
  854. If ``host`` is a vCenter host, then use esxi_hosts to execute this function
  855. on a list of one or more ESXi machines.
  856. credstore
  857. Optionally set to path to the credential store file.
  858. :return: Dictionary with keys and values corresponding to the
  859. syslog configuration, per host.
  860. CLI Example:
  861. .. code-block:: bash
  862. # Used for ESXi host connection information
  863. salt '*' vsphere.get_syslog_config my.esxi.host root bad-password
  864. # Used for connecting to a vCenter Server
  865. salt '*' vsphere.get_syslog_config my.vcenter.location root bad-password \
  866. esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
  867. '''
  868. cmd = 'system syslog config get'
  869. ret = {}
  870. if esxi_hosts:
  871. if not isinstance(esxi_hosts, list):
  872. raise CommandExecutionError('\'esxi_hosts\' must be a list.')
  873. for esxi_host in esxi_hosts:
  874. response = salt.utils.vmware.esxcli(host, username, password, cmd,
  875. protocol=protocol, port=port,
  876. esxi_host=esxi_host, credstore=credstore)
  877. # format the response stdout into something useful
  878. ret.update({esxi_host: _format_syslog_config(response)})
  879. else:
  880. # Handles a single host or a vCenter connection when no esxi_hosts are provided.
  881. response = salt.utils.vmware.esxcli(host, username, password, cmd,
  882. protocol=protocol, port=port,
  883. credstore=credstore)
  884. # format the response stdout into something useful
  885. ret.update({host: _format_syslog_config(response)})
  886. return ret
  887. @depends(HAS_ESX_CLI)
  888. def reset_syslog_config(host,
  889. username,
  890. password,
  891. protocol=None,
  892. port=None,
  893. syslog_config=None,
  894. esxi_hosts=None,
  895. credstore=None):
  896. '''
  897. Reset the syslog service to its default settings.
  898. Valid syslog_config values are ``logdir``, ``loghost``, ``logdir-unique``,
  899. ``default-rotate``, ``default-size``, ``default-timeout``,
  900. or ``all`` for all of these.
  901. host
  902. The location of the host.
  903. username
  904. The username used to login to the host, such as ``root``.
  905. password
  906. The password used to login to the host.
  907. protocol
  908. Optionally set to alternate protocol if the host is not using the default
  909. protocol. Default protocol is ``https``.
  910. port
  911. Optionally set to alternate port if the host is not using the default
  912. port. Default port is ``443``.
  913. syslog_config
  914. List of parameters to reset, provided as a comma-delimited string, or 'all' to
  915. reset all syslog configuration parameters. Required.
  916. esxi_hosts
  917. If ``host`` is a vCenter host, then use esxi_hosts to execute this function
  918. on a list of one or more ESXi machines.
  919. credstore
  920. Optionally set to path to the credential store file.
  921. :return: Dictionary with a top-level key of 'success' which indicates
  922. if all the parameters were reset, and individual keys
  923. for each parameter indicating which succeeded or failed, per host.
  924. CLI Example:
  925. ``syslog_config`` can be passed as a quoted, comma-separated string, e.g.
  926. .. code-block:: bash
  927. # Used for ESXi host connection information
  928. salt '*' vsphere.reset_syslog_config my.esxi.host root bad-password \
  929. syslog_config='logdir,loghost'
  930. # Used for connecting to a vCenter Server
  931. salt '*' vsphere.reset_syslog_config my.vcenter.location root bad-password \
  932. syslog_config='logdir,loghost' esxi_hosts='[esxi-1.host.com, esxi-2.host.com]'
  933. '''
  934. if not syslog_config:
  935. raise CommandExecutionError('The \'reset_syslog_config\' function requires a '
  936. '\'syslog_config\' setting.')
  937. valid_resets = ['logdir', 'loghost', 'default-rotate',
  938. 'default-size', 'default-timeout', 'logdir-unique']
  939. cmd = 'system syslog config set --reset='
  940. if ',' in syslog_config:
  941. resets = [ind_reset.strip() for ind_reset in syslog_config.split(',')]
  942. elif syslog_config == 'all':
  943. resets = valid_resets
  944. else:
  945. resets = [syslog_config]
  946. ret = {}
  947. if esxi_hosts:
  948. if not isinstance(esxi_hosts, list):
  949. raise CommandExecutionError('\'esxi_hosts\' must be a list.')
  950. for esxi_host in esxi_hosts:
  951. response_dict = _reset_syslog_config_params(host, username, password,
  952. cmd, resets, valid_resets,
  953. protocol=protocol, port=port,
  954. esxi_host=esxi_host, credstore=credstore)
  955. ret.update({esxi_host: response_dict})
  956. else:
  957. # Handles a single host or a vCenter connection when no esxi_hosts are provided.
  958. response_dict = _reset_syslog_config_params(host, username, password,
  959. cmd, resets, valid_resets,
  960. protocol=protocol, port=port,
  961. credstore=credstore)
  962. ret.update({host: response_dict})
  963. return ret
  964. @ignores_kwargs('credstore')
  965. def upload_ssh_key(host, username, password, ssh_key=None, ssh_key_file=None,
  966. protocol=None, port=None, certificate_verify=False):
  967. '''
  968. Upload an ssh key for root to an ESXi host via http PUT.
  969. This function only works for ESXi, not vCenter.
  970. Only one ssh key can be uploaded for root. Uploading a second key will
  971. replace any existing key.
  972. :param host: The location of the ESXi Host
  973. :param username: Username to connect as
  974. :param password: Password for the ESXi web endpoint
  975. :param ssh_key: Public SSH key, will be added to authorized_keys on ESXi
  976. :param ssh_key_file: File containing the SSH key. Use 'ssh_key' or
  977. ssh_key_file, but not both.
  978. :param protocol: defaults to https, can be http if ssl is disabled on ESXi
  979. :param port: defaults to 443 for https
  980. :param certificate_verify: If true require that the SSL connection present
  981. a valid certificate
  982. :return: Dictionary with a 'status' key, True if upload is successful.
  983. If upload is unsuccessful, 'status' key will be False and
  984. an 'Error' key will have an informative message.
  985. CLI Example:
  986. .. code-block:: bash
  987. salt '*' vsphere.upload_ssh_key my.esxi.host root bad-password ssh_key_file='/etc/salt/my_keys/my_key.pub'
  988. '''
  989. if protocol is None:
  990. protocol = 'https'
  991. if port is None:
  992. port = 443
  993. url = '{0}://{1}:{2}/host/ssh_root_authorized_keys'.format(protocol,
  994. host,
  995. port)
  996. ret = {}
  997. result = None
  998. try:
  999. if ssh_key:
  1000. result = salt.utils.http.query(url,
  1001. status=True,
  1002. text=True,
  1003. method='PUT',
  1004. username=username,
  1005. password=password,
  1006. data=ssh_key,
  1007. verify_ssl=certificate_verify)
  1008. elif ssh_key_file:
  1009. result = salt.utils.http.query(url,
  1010. status=True,
  1011. text=True,
  1012. method='PUT',
  1013. username=username,
  1014. password=password,
  1015. data_file=ssh_key_file,
  1016. data_render=False,
  1017. verify_ssl=certificate_verify)
  1018. if result.get('status') == 200:
  1019. ret['status'] = True
  1020. else:
  1021. ret['status'] = False
  1022. ret['Error'] = result['error']
  1023. except Exception as msg:
  1024. ret['status'] = False
  1025. ret['Error'] = msg
  1026. return ret
  1027. @ignores_kwargs('credstore')
  1028. def get_ssh_key(host,
  1029. username,
  1030. password,
  1031. protocol=None,
  1032. port=None,
  1033. certificate_verify=False):
  1034. '''
  1035. Retrieve the authorized_keys entry for root.
  1036. This function only works for ESXi, not vCenter.
  1037. :param host: The location of the ESXi Host
  1038. :param username: Username to connect as
  1039. :param password: Password for the ESXi web endpoint
  1040. :param protocol: defaults to https, can be http if ssl is disabled on ESXi
  1041. :param port: defaults to 443 for https
  1042. :param certificate_verify: If true require that the SSL connection present
  1043. a valid certificate
  1044. :return: True if upload is successful
  1045. CLI Example:
  1046. .. code-block:: bash
  1047. salt '*' vsphere.get_ssh_key my.esxi.host root bad-password certificate_verify=True
  1048. '''
  1049. if protocol is None:
  1050. protocol = 'https'
  1051. if port is None:
  1052. port = 443
  1053. url = '{0}://{1}:{2}/host/ssh_root_authorized_keys'.format(protocol,
  1054. host,
  1055. port)
  1056. ret = {}
  1057. try:
  1058. result = salt.utils.http.query(url,
  1059. status…

Large files files are truncated, but you can click here to view the full file