mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 17:09:03 +00:00
Merge branch 'develop' into unicoded-wildcard-route53
This commit is contained in:
commit
7716784015
2
.ci/docs
2
.ci/docs
@ -22,7 +22,7 @@ pipeline {
|
||||
stage('build') {
|
||||
steps {
|
||||
sh 'eval "$(pyenv init -)"; make -C doc clean html'
|
||||
archiveArtifacts artifacts: 'doc/_build/html'
|
||||
archiveArtifacts artifacts: 'doc/_build/html/'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
59
doc/conf.py
59
doc/conf.py
@ -129,55 +129,56 @@ MOCK_MODULES = [
|
||||
# modules, renderers, states, returners, et al
|
||||
'ClusterShell',
|
||||
'ClusterShell.NodeSet',
|
||||
'django',
|
||||
'libvirt',
|
||||
'MySQLdb',
|
||||
'MySQLdb.cursors',
|
||||
'nagios_json',
|
||||
'psutil',
|
||||
'pycassa',
|
||||
'pymongo',
|
||||
'rabbitmq_server',
|
||||
'redis',
|
||||
#'requests',
|
||||
#'requests.exceptions',
|
||||
'rpm',
|
||||
'rpmUtils',
|
||||
'rpmUtils.arch',
|
||||
'yum',
|
||||
'OpenSSL',
|
||||
'zfs',
|
||||
'salt.ext.six.moves.winreg',
|
||||
'win32security',
|
||||
'ntsecuritycon',
|
||||
'napalm',
|
||||
'avahi',
|
||||
'boto.regioninfo',
|
||||
'concurrent',
|
||||
'dbus',
|
||||
'django',
|
||||
'dns',
|
||||
'dns.resolver',
|
||||
'dson',
|
||||
'hjson',
|
||||
'jnpr',
|
||||
'json',
|
||||
'lxml',
|
||||
'lxml.etree',
|
||||
'jnpr.junos',
|
||||
'jnpr.junos.utils',
|
||||
'jnpr.junos.utils.config',
|
||||
'jnpr.junos.utils.sw',
|
||||
'dns',
|
||||
'dns.resolver',
|
||||
'json',
|
||||
'keyring',
|
||||
'libvirt',
|
||||
'lxml',
|
||||
'lxml.etree',
|
||||
'msgpack',
|
||||
'nagios_json',
|
||||
'napalm',
|
||||
'netaddr',
|
||||
'netaddr.IPAddress',
|
||||
'netaddr.core',
|
||||
'netaddr.core.AddrFormatError',
|
||||
'ntsecuritycon',
|
||||
'psutil',
|
||||
'pycassa',
|
||||
'pyconnman',
|
||||
'pyiface',
|
||||
'pymongo',
|
||||
'pyroute2',
|
||||
'pyroute2.ipdb',
|
||||
'avahi',
|
||||
'dbus',
|
||||
'rabbitmq_server',
|
||||
'redis',
|
||||
'rpm',
|
||||
'rpmUtils',
|
||||
'rpmUtils.arch',
|
||||
'salt.ext.six.moves.winreg',
|
||||
'twisted',
|
||||
'twisted.internet',
|
||||
'twisted.internet.protocol',
|
||||
'twisted.internet.protocol.DatagramProtocol',
|
||||
'msgpack',
|
||||
'boto.regioninfo',
|
||||
'win32security',
|
||||
'yum',
|
||||
'zfs',
|
||||
]
|
||||
|
||||
for mod_name in MOCK_MODULES:
|
||||
@ -255,7 +256,7 @@ on_saltstack = 'SALT_ON_SALTSTACK' in os.environ
|
||||
project = 'Salt'
|
||||
|
||||
version = salt.version.__version__
|
||||
latest_release = '2018.3.1' # latest release
|
||||
latest_release = '2018.3.2' # latest release
|
||||
previous_release = '2017.7.6' # latest release from previous branch
|
||||
previous_release_dir = '2017.7' # path on web server for previous branch
|
||||
next_release = '' # next release
|
||||
|
@ -1,6 +1,6 @@
|
||||
==================
|
||||
salt.proxy.netmiko
|
||||
==================
|
||||
=====================
|
||||
salt.proxy.netmiko_px
|
||||
=====================
|
||||
|
||||
.. automodule:: salt.proxy.netmiko_px
|
||||
:members:
|
||||
|
@ -18,6 +18,7 @@ sdb modules
|
||||
etcd_db
|
||||
keyring_db
|
||||
memcached
|
||||
redis_sdb
|
||||
rest
|
||||
sqlite3
|
||||
tism
|
||||
|
5
doc/ref/sdb/all/salt.sdb.redis_sdb.rst
Normal file
5
doc/ref/sdb/all/salt.sdb.redis_sdb.rst
Normal file
@ -0,0 +1,5 @@
|
||||
salt.sdb.redis_sdb module
|
||||
=========================
|
||||
|
||||
.. automodule:: salt.sdb.redis_sdb
|
||||
:members:
|
@ -472,6 +472,19 @@ EC2 API or AWS Console.
|
||||
spot_config:
|
||||
spot_price: 0.10
|
||||
|
||||
You can optionally specify tags to apply to the EC2 spot instance request.
|
||||
A spot instance request itself is an object in AWS. The following example
|
||||
will set two tags on the spot instance request.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
my-ec2-config:
|
||||
spot_config:
|
||||
spot_price: 0.10
|
||||
tag:
|
||||
tag0: value
|
||||
tag1: value
|
||||
|
||||
By default, the spot instance type is set to 'one-time', meaning it will
|
||||
be launched and, if it's ever terminated for whatever reason, it will not
|
||||
be recreated. If you would like your spot instances to be relaunched after
|
||||
|
@ -1,9 +1,8 @@
|
||||
========================================
|
||||
In Progress: Salt 2018.3.2 Release Notes
|
||||
========================================
|
||||
===========================
|
||||
Salt 2018.3.2 Release Notes
|
||||
===========================
|
||||
|
||||
Version 2018.3.2 is an **unreleased** bugfix release for :ref:`2018.3.0 <release-2018-3-0>`.
|
||||
This release is still in progress and has not been released yet.
|
||||
Version 2018.3.2 is a bugfix release for :ref:`2018.3.0 <release-2018-3-0>`.
|
||||
|
||||
The ``2018.3.2`` release contains only a small number of fixes, detailed below.
|
||||
|
||||
|
@ -246,7 +246,7 @@ the new virtual machine on. Using ``salt://`` assumes that the CentOS virtual
|
||||
machine image is located in the root of the :ref:`file-server` on the master.
|
||||
When images are cloned (i.e. copied locatlly after retrieval from the file server)
|
||||
the destination directory on the hypervisor minion is determined by the ``virt:images``
|
||||
config option; by default this is ``/srv/salt/salt-images/``.
|
||||
config option; by default this is ``/srv/salt-images/``.
|
||||
|
||||
When a VM is initialized using ``virt.init`` the image is copied to the hypervisor
|
||||
using ``cp.cache_file`` and will be mounted and seeded with a minion. Seeding includes
|
||||
|
@ -2059,6 +2059,8 @@ def request_instance(vm_=None, call=None):
|
||||
if spot_config:
|
||||
sir_id = data[0]['spotInstanceRequestId']
|
||||
|
||||
vm_['spotRequestId'] = sir_id
|
||||
|
||||
def __query_spot_instance_request(sir_id, location):
|
||||
params = {'Action': 'DescribeSpotInstanceRequests',
|
||||
'SpotInstanceRequestId.1': sir_id}
|
||||
@ -2681,6 +2683,51 @@ def create(vm_=None, call=None):
|
||||
location=location
|
||||
)
|
||||
|
||||
# Once instance tags are set, tag the spot request if configured
|
||||
if 'spot_config' in vm_ and 'tag' in vm_['spot_config']:
|
||||
|
||||
if not isinstance(vm_['spot_config']['tag'], dict):
|
||||
raise SaltCloudConfigError(
|
||||
'\'tag\' should be a dict.'
|
||||
)
|
||||
|
||||
for value in six.itervalues(vm_['spot_config']['tag']):
|
||||
if not isinstance(value, str):
|
||||
raise SaltCloudConfigError(
|
||||
'\'tag\' values must be strings. Try quoting the values. '
|
||||
'e.g. "2013-09-19T20:09:46Z".'
|
||||
)
|
||||
|
||||
spot_request_tags = {}
|
||||
|
||||
if 'spotRequestId' not in vm_:
|
||||
raise SaltCloudConfigError('Failed to find spotRequestId')
|
||||
|
||||
sir_id = vm_['spotRequestId']
|
||||
|
||||
spot_request_tags['Name'] = vm_['name']
|
||||
|
||||
for k, v in six.iteritems(vm_['spot_config']['tag']):
|
||||
spot_request_tags[k] = v
|
||||
|
||||
__utils__['cloud.fire_event'](
|
||||
'event',
|
||||
'setting tags',
|
||||
'salt/cloud/spot_request_{0}/tagging'.format(sir_id),
|
||||
args={'tags': spot_request_tags},
|
||||
sock_dir=__opts__['sock_dir'],
|
||||
transport=__opts__['transport']
|
||||
)
|
||||
salt.utils.cloud.wait_for_fun(
|
||||
set_tags,
|
||||
timeout=30,
|
||||
name=vm_['name'],
|
||||
tags=spot_request_tags,
|
||||
instance_id=sir_id,
|
||||
call='action',
|
||||
location=location
|
||||
)
|
||||
|
||||
network_interfaces = config.get_cloud_config_value(
|
||||
'network_interfaces',
|
||||
vm_,
|
||||
|
@ -36,144 +36,127 @@ in a configuration block under the ``netmiko`` key in the configuration opts
|
||||
simultaneously. These fields are the exact same supported by the ``netmiko``
|
||||
Proxy Module:
|
||||
|
||||
device_type
|
||||
Class selection based on device type. Supported options:
|
||||
- ``device_type`` - Class selection based on device type. Supported options:
|
||||
|
||||
- ``a10``: A10 Networks
|
||||
- ``accedian``: Accedian Networks
|
||||
- ``alcatel_aos``: Alcatel AOS
|
||||
- ``alcatel_sros``: Alcatel SROS
|
||||
- ``apresia_aeos``: Apresia AEOS
|
||||
- ``arista_eos``: Arista EOS
|
||||
- ``aruba_os``: Aruba
|
||||
- ``avaya_ers``: Avaya ERS
|
||||
- ``avaya_vsp``: Avaya VSP
|
||||
- ``brocade_fastiron``: Brocade Fastiron
|
||||
- ``brocade_netiron``: Brocade Netiron
|
||||
- ``brocade_nos``: Brocade NOS
|
||||
- ``brocade_vdx``: Brocade NOS
|
||||
- ``brocade_vyos``: VyOS
|
||||
- ``checkpoint_gaia``: Check Point GAiA
|
||||
- ``calix_b6``: Calix B6
|
||||
- ``ciena_saos``: Ciena SAOS
|
||||
- ``cisco_asa``: Cisco SA
|
||||
- ``cisco_ios``: Cisco IOS
|
||||
- ``cisco_nxos``: Cisco NX-oS
|
||||
- ``cisco_s300``: Cisco S300
|
||||
- ``cisco_tp``: Cisco TpTcCe
|
||||
- ``cisco_wlc``: Cisco WLC
|
||||
- ``cisco_xe``: Cisco IOS
|
||||
- ``cisco_xr``: Cisco XR
|
||||
- ``coriant``: Coriant
|
||||
- ``dell_force10``: Dell Force10
|
||||
- ``dell_os10``: Dell OS10
|
||||
- ``dell_powerconnect``: Dell PowerConnect
|
||||
- ``eltex``: Eltex
|
||||
- ``enterasys``: Enterasys
|
||||
- ``extreme``: Extreme
|
||||
- ``extreme_wing``: Extreme Wing
|
||||
- ``f5_ltm``: F5 LTM
|
||||
- ``fortinet``: Fortinet
|
||||
- ``generic_termserver``: TerminalServer
|
||||
- ``hp_comware``: HP Comware
|
||||
- ``hp_procurve``: HP Procurve
|
||||
- ``huawei``: Huawei
|
||||
- ``huawei_vrpv8``: Huawei VRPV8
|
||||
- ``juniper``: Juniper Junos
|
||||
- ``juniper_junos``: Juniper Junos
|
||||
- ``linux``: Linux
|
||||
- ``mellanox``: Mellanox
|
||||
- ``mrv_optiswitch``: MrvOptiswitch
|
||||
- ``netapp_cdot``: NetAppcDot
|
||||
- ``netscaler``: Netscaler
|
||||
- ``ovs_linux``: OvsLinux
|
||||
- ``paloalto_panos``: PaloAlto Panos
|
||||
- ``pluribus``: Pluribus
|
||||
- ``quanta_mesh``: Quanta Mesh
|
||||
- ``ruckus_fastiron``: Ruckus Fastiron
|
||||
- ``ubiquiti_edge``: Ubiquiti Edge
|
||||
- ``ubiquiti_edgeswitch``: Ubiquiti Edge
|
||||
- ``vyatta_vyos``: VyOS
|
||||
- ``vyos``: VyOS
|
||||
- ``brocade_fastiron_telnet``: Brocade Fastiron over Telnet
|
||||
- ``brocade_netiron_telnet``: Brocade Netiron over Telnet
|
||||
- ``cisco_ios_telnet``: Cisco IOS over Telnet
|
||||
- ``apresia_aeos_telnet``: Apresia AEOS over Telnet
|
||||
- ``arista_eos_telnet``: Arista EOS over Telnet
|
||||
- ``hp_procurve_telnet``: HP Procurve over Telnet
|
||||
- ``hp_comware_telnet``: HP Comware over Telnet
|
||||
- ``juniper_junos_telnet``: Juniper Junos over Telnet
|
||||
- ``calix_b6_telnet``: Calix B6 over Telnet
|
||||
- ``dell_powerconnect_telnet``: Dell PowerConnect over Telnet
|
||||
- ``generic_termserver_telnet``: TerminalServer over Telnet
|
||||
- ``extreme_telnet``: Extreme Networks over Telnet
|
||||
- ``ruckus_fastiron_telnet``: Ruckus Fastiron over Telnet
|
||||
- ``cisco_ios_serial``: Cisco IOS over serial port
|
||||
- ``a10``: A10 Networks
|
||||
- ``accedian``: Accedian Networks
|
||||
- ``alcatel_aos``: Alcatel AOS
|
||||
- ``alcatel_sros``: Alcatel SROS
|
||||
- ``apresia_aeos``: Apresia AEOS
|
||||
- ``arista_eos``: Arista EOS
|
||||
- ``aruba_os``: Aruba
|
||||
- ``avaya_ers``: Avaya ERS
|
||||
- ``avaya_vsp``: Avaya VSP
|
||||
- ``brocade_fastiron``: Brocade Fastiron
|
||||
- ``brocade_netiron``: Brocade Netiron
|
||||
- ``brocade_nos``: Brocade NOS
|
||||
- ``brocade_vdx``: Brocade NOS
|
||||
- ``brocade_vyos``: VyOS
|
||||
- ``checkpoint_gaia``: Check Point GAiA
|
||||
- ``calix_b6``: Calix B6
|
||||
- ``ciena_saos``: Ciena SAOS
|
||||
- ``cisco_asa``: Cisco SA
|
||||
- ``cisco_ios``: Cisco IOS
|
||||
- ``cisco_nxos``: Cisco NX-oS
|
||||
- ``cisco_s300``: Cisco S300
|
||||
- ``cisco_tp``: Cisco TpTcCe
|
||||
- ``cisco_wlc``: Cisco WLC
|
||||
- ``cisco_xe``: Cisco IOS
|
||||
- ``cisco_xr``: Cisco XR
|
||||
- ``coriant``: Coriant
|
||||
- ``dell_force10``: Dell Force10
|
||||
- ``dell_os10``: Dell OS10
|
||||
- ``dell_powerconnect``: Dell PowerConnect
|
||||
- ``eltex``: Eltex
|
||||
- ``enterasys``: Enterasys
|
||||
- ``extreme``: Extreme
|
||||
- ``extreme_wing``: Extreme Wing
|
||||
- ``f5_ltm``: F5 LTM
|
||||
- ``fortinet``: Fortinet
|
||||
- ``generic_termserver``: TerminalServer
|
||||
- ``hp_comware``: HP Comware
|
||||
- ``hp_procurve``: HP Procurve
|
||||
- ``huawei``: Huawei
|
||||
- ``huawei_vrpv8``: Huawei VRPV8
|
||||
- ``juniper``: Juniper Junos
|
||||
- ``juniper_junos``: Juniper Junos
|
||||
- ``linux``: Linux
|
||||
- ``mellanox``: Mellanox
|
||||
- ``mrv_optiswitch``: MrvOptiswitch
|
||||
- ``netapp_cdot``: NetAppcDot
|
||||
- ``netscaler``: Netscaler
|
||||
- ``ovs_linux``: OvsLinux
|
||||
- ``paloalto_panos``: PaloAlto Panos
|
||||
- ``pluribus``: Pluribus
|
||||
- ``quanta_mesh``: Quanta Mesh
|
||||
- ``ruckus_fastiron``: Ruckus Fastiron
|
||||
- ``ubiquiti_edge``: Ubiquiti Edge
|
||||
- ``ubiquiti_edgeswitch``: Ubiquiti Edge
|
||||
- ``vyatta_vyos``: VyOS
|
||||
- ``vyos``: VyOS
|
||||
- ``brocade_fastiron_telnet``: Brocade Fastiron over Telnet
|
||||
- ``brocade_netiron_telnet``: Brocade Netiron over Telnet
|
||||
- ``cisco_ios_telnet``: Cisco IOS over Telnet
|
||||
- ``apresia_aeos_telnet``: Apresia AEOS over Telnet
|
||||
- ``arista_eos_telnet``: Arista EOS over Telnet
|
||||
- ``hp_procurve_telnet``: HP Procurve over Telnet
|
||||
- ``hp_comware_telnet``: HP Comware over Telnet
|
||||
- ``juniper_junos_telnet``: Juniper Junos over Telnet
|
||||
- ``calix_b6_telnet``: Calix B6 over Telnet
|
||||
- ``dell_powerconnect_telnet``: Dell PowerConnect over Telnet
|
||||
- ``generic_termserver_telnet``: TerminalServer over Telnet
|
||||
- ``extreme_telnet``: Extreme Networks over Telnet
|
||||
- ``ruckus_fastiron_telnet``: Ruckus Fastiron over Telnet
|
||||
- ``cisco_ios_serial``: Cisco IOS over serial port
|
||||
|
||||
ip
|
||||
IP address of target device. Not required if ``host`` is provided.
|
||||
- ``ip`` - IP address of target device (not required if ``host`` is provided)
|
||||
|
||||
host
|
||||
Hostname of target device. Not required if ``ip`` is provided.
|
||||
- ``host`` - Hostname of target device (not required if ``ip`` is provided)
|
||||
|
||||
username
|
||||
Username to authenticate against target device if required.
|
||||
- ``username`` - Username to authenticate against target device, if required
|
||||
|
||||
password
|
||||
Password to authenticate against target device if required.
|
||||
- ``password`` - Password to authenticate against target device, if required
|
||||
|
||||
secret
|
||||
The enable password if target device requires one.
|
||||
- ``secret`` - The enable password if target device requires one
|
||||
|
||||
port
|
||||
The destination port used to connect to the target device.
|
||||
- ``port`` - The destination port used to connect to the target device
|
||||
|
||||
global_delay_factor: ``1``
|
||||
Multiplication factor affecting Netmiko delays (default: ``1``).
|
||||
- ``global_delay_factor`` - Multiplication factor affecting Netmiko delays
|
||||
(default: ``1``)
|
||||
|
||||
use_keys: ``False``
|
||||
Connect to target device using SSH keys.
|
||||
- ``use_keys`` - Connect to target device using SSH keys (default: ``False``)
|
||||
|
||||
key_file
|
||||
Filename path of the SSH key file to use.
|
||||
- ``key_file`` - Filename path of the SSH key file to use
|
||||
|
||||
allow_agent
|
||||
Enable use of SSH key-agent.
|
||||
- ``allow_agent`` - Enable use of SSH key-agent
|
||||
|
||||
ssh_strict: ``False``
|
||||
Automatically reject unknown SSH host keys (default: ``False``, which means
|
||||
unknown SSH host keys will be accepted).
|
||||
- ``ssh_strict`` - Automatically reject unknown SSH host keys (default:
|
||||
``False``, which means unknown SSH host keys will be accepted)
|
||||
|
||||
system_host_keys: ``False``
|
||||
Load host keys from the user's 'known_hosts' file.
|
||||
- ``system_host_keys`` - Load host keys from the user's "known_hosts" file
|
||||
(default: ``False``)
|
||||
|
||||
alt_host_keys: ``False``
|
||||
If ``True`` host keys will be loaded from the file specified in
|
||||
``alt_key_file``.
|
||||
- ``alt_host_keys`` - If ``True``, host keys will be loaded from the file
|
||||
specified in ``alt_key_file`` (default: ``False``)
|
||||
|
||||
alt_key_file
|
||||
SSH host key file to use (if ``alt_host_keys=True``).
|
||||
- ``alt_key_file`` - SSH host key file to use (if ``alt_host_keys=True``)
|
||||
|
||||
ssh_config_file
|
||||
File name of OpenSSH configuration file.
|
||||
- ``ssh_config_file`` - File name of OpenSSH configuration file
|
||||
|
||||
timeout: ``90``
|
||||
Connection timeout (in seconds).
|
||||
- ``timeout`` - Connection timeout, in seconds (default: ``90``)
|
||||
|
||||
session_timeout: ``60``
|
||||
Set a timeout for parallel requests (in seconds).
|
||||
- ``session_timeout`` - Set a timeout for parallel requests, in seconds
|
||||
(default: ``60``)
|
||||
|
||||
keepalive: ``0``
|
||||
Send SSH keepalive packets at a specific interval, in seconds. Currently
|
||||
defaults to ``0``, for backwards compatibility (it will not attempt to keep
|
||||
the connection alive using the KEEPALIVE packets).
|
||||
- ``keepalive`` - Send SSH keepalive packets at a specific interval, in
|
||||
seconds. Currently defaults to ``0``, for backwards compatibility (it will
|
||||
not attempt to keep the connection alive using the KEEPALIVE packets).
|
||||
|
||||
default_enter: ``\n``
|
||||
Character(s) to send to correspond to enter key (default: ``\n``).
|
||||
- ``default_enter`` - Character(s) to send to correspond to enter key (default:
|
||||
``\\n``)
|
||||
|
||||
response_return: ``\n``
|
||||
Character(s) to use in normalized return data to represent enter key
|
||||
(default: ``\n``)
|
||||
- ``response_return`` - Character(s) to use in normalized return data to
|
||||
represent enter key (default: ``\\n``)
|
||||
|
||||
Example (when not running in a ``netmiko`` Proxy Minion):
|
||||
|
||||
|
@ -8,7 +8,6 @@ The networking module for NI Linux Real-Time distro
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
import logging
|
||||
import time
|
||||
import configparser
|
||||
import os
|
||||
|
||||
# Import salt libs
|
||||
@ -18,6 +17,7 @@ import salt.exceptions
|
||||
|
||||
# Import 3rd-party libs
|
||||
from salt.ext import six
|
||||
from salt.ext.six.moves import configparser
|
||||
try:
|
||||
import pyconnman
|
||||
HAS_PYCONNMAN = True
|
||||
|
@ -91,14 +91,9 @@ def send_msg(recipient,
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
smtp.send_msg 'admin@example.com' 'This is a salt module test' \
|
||||
profile='my-smtp-account'
|
||||
smtp.send_msg 'admin@example.com' 'This is a salt module test' \
|
||||
username='myuser' password='verybadpass' sender="admin@example.com' \
|
||||
server='smtp.domain.com'
|
||||
smtp.send_msg 'admin@example.com' 'This is a salt module test' \
|
||||
username='myuser' password='verybadpass' sender="admin@example.com' \
|
||||
server='smtp.domain.com' attachments="['/var/log/messages']"
|
||||
salt '*' smtp.send_msg 'admin@example.com' 'This is a salt module test' profile='my-smtp-account'
|
||||
salt '*' smtp.send_msg 'admin@example.com' 'This is a salt module test' username='myuser' password='verybadpass' sender='admin@example.com' server='smtp.domain.com'
|
||||
salt '*' smtp.send_msg 'admin@example.com' 'This is a salt module test' username='myuser' password='verybadpass' sender='admin@example.com' server='smtp.domain.com' attachments="['/var/log/messages']"
|
||||
'''
|
||||
if profile:
|
||||
creds = __salt__['config.option'](profile)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -134,10 +134,10 @@ import salt.utils.yaml
|
||||
# Import third party libs
|
||||
try:
|
||||
import consul
|
||||
HAS_CONSUL = True
|
||||
CONSUL_VERSION = consul.__version__
|
||||
if not hasattr(consul, '__version__'):
|
||||
consul.__version__ = '0.1' # Some packages has no version, and so this pillar crashes on access to it.
|
||||
except ImportError:
|
||||
HAS_CONSUL = False
|
||||
consul = None
|
||||
|
||||
__virtualname__ = 'consul'
|
||||
|
||||
@ -149,7 +149,7 @@ def __virtual__():
|
||||
'''
|
||||
Only return if python-consul is installed
|
||||
'''
|
||||
return __virtualname__ if HAS_CONSUL else False
|
||||
return __virtualname__ if consul is not None else False
|
||||
|
||||
|
||||
def ext_pillar(minion_id,
|
||||
@ -290,9 +290,9 @@ def get_conn(opts, profile):
|
||||
pillarenv = opts_merged.get('pillarenv') or 'base'
|
||||
params['dc'] = _resolve_datacenter(params['dc'], pillarenv)
|
||||
|
||||
if HAS_CONSUL:
|
||||
if consul:
|
||||
# Sanity check. ACL Tokens are supported on python-consul 0.4.7 onwards only.
|
||||
if CONSUL_VERSION < '0.4.7' and params.get('target'):
|
||||
if consul.__version__ < '0.4.7' and params.get('target'):
|
||||
params.pop('target')
|
||||
return consul.Consul(**params)
|
||||
else:
|
||||
|
@ -24,155 +24,137 @@ Pillar
|
||||
The ``netmiko`` proxy configuration requires the following parameters in order
|
||||
to connect to the network device:
|
||||
|
||||
device_type
|
||||
Class selection based on device type. Supported options:
|
||||
- ``device_type`` - Class selection based on device type. Supported options:
|
||||
|
||||
- ``a10``: A10 Networks
|
||||
- ``accedian``: Accedian Networks
|
||||
- ``alcatel_aos``: Alcatel AOS
|
||||
- ``alcatel_sros``: Alcatel SROS
|
||||
- ``apresia_aeos``: Apresia AEOS
|
||||
- ``arista_eos``: Arista EOS
|
||||
- ``aruba_os``: Aruba
|
||||
- ``avaya_ers``: Avaya ERS
|
||||
- ``avaya_vsp``: Avaya VSP
|
||||
- ``brocade_fastiron``: Brocade Fastiron
|
||||
- ``brocade_netiron``: Brocade Netiron
|
||||
- ``brocade_nos``: Brocade NOS
|
||||
- ``brocade_vdx``: Brocade NOS
|
||||
- ``brocade_vyos``: VyOS
|
||||
- ``checkpoint_gaia``: Check Point GAiA
|
||||
- ``calix_b6``: Calix B6
|
||||
- ``ciena_saos``: Ciena SAOS
|
||||
- ``cisco_asa``: Cisco SA
|
||||
- ``cisco_ios``: Cisco IOS
|
||||
- ``cisco_nxos``: Cisco NX-oS
|
||||
- ``cisco_s300``: Cisco S300
|
||||
- ``cisco_tp``: Cisco TpTcCe
|
||||
- ``cisco_wlc``: Cisco WLC
|
||||
- ``cisco_xe``: Cisco IOS
|
||||
- ``cisco_xr``: Cisco XR
|
||||
- ``coriant``: Coriant
|
||||
- ``dell_force10``: Dell Force10
|
||||
- ``dell_os10``: Dell OS10
|
||||
- ``dell_powerconnect``: Dell PowerConnect
|
||||
- ``eltex``: Eltex
|
||||
- ``enterasys``: Enterasys
|
||||
- ``extreme``: Extreme
|
||||
- ``extreme_wing``: Extreme Wing
|
||||
- ``f5_ltm``: F5 LTM
|
||||
- ``fortinet``: Fortinet
|
||||
- ``generic_termserver``: TerminalServer
|
||||
- ``hp_comware``: HP Comware
|
||||
- ``hp_procurve``: HP Procurve
|
||||
- ``huawei``: Huawei
|
||||
- ``huawei_vrpv8``: Huawei VRPV8
|
||||
- ``juniper``: Juniper Junos
|
||||
- ``juniper_junos``: Juniper Junos
|
||||
- ``linux``: Linux
|
||||
- ``mellanox``: Mellanox
|
||||
- ``mrv_optiswitch``: MrvOptiswitch
|
||||
- ``netapp_cdot``: NetAppcDot
|
||||
- ``netscaler``: Netscaler
|
||||
- ``ovs_linux``: OvsLinux
|
||||
- ``paloalto_panos``: PaloAlto Panos
|
||||
- ``pluribus``: Pluribus
|
||||
- ``quanta_mesh``: Quanta Mesh
|
||||
- ``ruckus_fastiron``: Ruckus Fastiron
|
||||
- ``ubiquiti_edge``: Ubiquiti Edge
|
||||
- ``ubiquiti_edgeswitch``: Ubiquiti Edge
|
||||
- ``vyatta_vyos``: VyOS
|
||||
- ``vyos``: VyOS
|
||||
- ``brocade_fastiron_telnet``: Brocade Fastiron over Telnet
|
||||
- ``brocade_netiron_telnet``: Brocade Netiron over Telnet
|
||||
- ``cisco_ios_telnet``: Cisco IOS over Telnet
|
||||
- ``apresia_aeos_telnet``: Apresia AEOS over Telnet
|
||||
- ``arista_eos_telnet``: Arista EOS over Telnet
|
||||
- ``hp_procurve_telnet``: HP Procurve over Telnet
|
||||
- ``hp_comware_telnet``: HP Comware over Telnet
|
||||
- ``juniper_junos_telnet``: Juniper Junos over Telnet
|
||||
- ``calix_b6_telnet``: Calix B6 over Telnet
|
||||
- ``dell_powerconnect_telnet``: Dell PowerConnect over Telnet
|
||||
- ``generic_termserver_telnet``: TerminalServer over Telnet
|
||||
- ``extreme_telnet``: Extreme Networks over Telnet
|
||||
- ``ruckus_fastiron_telnet``: Ruckus Fastiron over Telnet
|
||||
- ``cisco_ios_serial``: Cisco IOS over serial port
|
||||
- ``a10``: A10 Networks
|
||||
- ``accedian``: Accedian Networks
|
||||
- ``alcatel_aos``: Alcatel AOS
|
||||
- ``alcatel_sros``: Alcatel SROS
|
||||
- ``apresia_aeos``: Apresia AEOS
|
||||
- ``arista_eos``: Arista EOS
|
||||
- ``aruba_os``: Aruba
|
||||
- ``avaya_ers``: Avaya ERS
|
||||
- ``avaya_vsp``: Avaya VSP
|
||||
- ``brocade_fastiron``: Brocade Fastiron
|
||||
- ``brocade_netiron``: Brocade Netiron
|
||||
- ``brocade_nos``: Brocade NOS
|
||||
- ``brocade_vdx``: Brocade NOS
|
||||
- ``brocade_vyos``: VyOS
|
||||
- ``checkpoint_gaia``: Check Point GAiA
|
||||
- ``calix_b6``: Calix B6
|
||||
- ``ciena_saos``: Ciena SAOS
|
||||
- ``cisco_asa``: Cisco SA
|
||||
- ``cisco_ios``: Cisco IOS
|
||||
- ``cisco_nxos``: Cisco NX-oS
|
||||
- ``cisco_s300``: Cisco S300
|
||||
- ``cisco_tp``: Cisco TpTcCe
|
||||
- ``cisco_wlc``: Cisco WLC
|
||||
- ``cisco_xe``: Cisco IOS
|
||||
- ``cisco_xr``: Cisco XR
|
||||
- ``coriant``: Coriant
|
||||
- ``dell_force10``: Dell Force10
|
||||
- ``dell_os10``: Dell OS10
|
||||
- ``dell_powerconnect``: Dell PowerConnect
|
||||
- ``eltex``: Eltex
|
||||
- ``enterasys``: Enterasys
|
||||
- ``extreme``: Extreme
|
||||
- ``extreme_wing``: Extreme Wing
|
||||
- ``f5_ltm``: F5 LTM
|
||||
- ``fortinet``: Fortinet
|
||||
- ``generic_termserver``: TerminalServer
|
||||
- ``hp_comware``: HP Comware
|
||||
- ``hp_procurve``: HP Procurve
|
||||
- ``huawei``: Huawei
|
||||
- ``huawei_vrpv8``: Huawei VRPV8
|
||||
- ``juniper``: Juniper Junos
|
||||
- ``juniper_junos``: Juniper Junos
|
||||
- ``linux``: Linux
|
||||
- ``mellanox``: Mellanox
|
||||
- ``mrv_optiswitch``: MrvOptiswitch
|
||||
- ``netapp_cdot``: NetAppcDot
|
||||
- ``netscaler``: Netscaler
|
||||
- ``ovs_linux``: OvsLinux
|
||||
- ``paloalto_panos``: PaloAlto Panos
|
||||
- ``pluribus``: Pluribus
|
||||
- ``quanta_mesh``: Quanta Mesh
|
||||
- ``ruckus_fastiron``: Ruckus Fastiron
|
||||
- ``ubiquiti_edge``: Ubiquiti Edge
|
||||
- ``ubiquiti_edgeswitch``: Ubiquiti Edge
|
||||
- ``vyatta_vyos``: VyOS
|
||||
- ``vyos``: VyOS
|
||||
- ``brocade_fastiron_telnet``: Brocade Fastiron over Telnet
|
||||
- ``brocade_netiron_telnet``: Brocade Netiron over Telnet
|
||||
- ``cisco_ios_telnet``: Cisco IOS over Telnet
|
||||
- ``apresia_aeos_telnet``: Apresia AEOS over Telnet
|
||||
- ``arista_eos_telnet``: Arista EOS over Telnet
|
||||
- ``hp_procurve_telnet``: HP Procurve over Telnet
|
||||
- ``hp_comware_telnet``: HP Comware over Telnet
|
||||
- ``juniper_junos_telnet``: Juniper Junos over Telnet
|
||||
- ``calix_b6_telnet``: Calix B6 over Telnet
|
||||
- ``dell_powerconnect_telnet``: Dell PowerConnect over Telnet
|
||||
- ``generic_termserver_telnet``: TerminalServer over Telnet
|
||||
- ``extreme_telnet``: Extreme Networks over Telnet
|
||||
- ``ruckus_fastiron_telnet``: Ruckus Fastiron over Telnet
|
||||
- ``cisco_ios_serial``: Cisco IOS over serial port
|
||||
|
||||
ip
|
||||
IP address of target device. Not required if ``host`` is provided.
|
||||
- ``ip`` - IP address of target device (not required if ``host`` is provided)
|
||||
|
||||
host
|
||||
Hostname of target device. Not required if ``ip`` is provided.
|
||||
- ``host`` - Hostname of target device (not required if ``ip`` is provided)
|
||||
|
||||
username
|
||||
Username to authenticate against target device if required.
|
||||
- ``username`` - Username to authenticate against target device, if required
|
||||
|
||||
password
|
||||
Password to authenticate against target device if required.
|
||||
- ``password`` - Password to authenticate against target device, if required
|
||||
|
||||
secret
|
||||
The enable password if target device requires one.
|
||||
- ``secret`` - The enable password if target device requires one
|
||||
|
||||
port
|
||||
The destination port used to connect to the target device.
|
||||
- ``port`` - The destination port used to connect to the target device
|
||||
|
||||
global_delay_factor: ``1``
|
||||
Multiplication factor affecting Netmiko delays (default: ``1``).
|
||||
- ``global_delay_factor`` - Multiplication factor affecting Netmiko delays
|
||||
(default: ``1``)
|
||||
|
||||
use_keys: ``False``
|
||||
Connect to target device using SSH keys.
|
||||
- ``use_keys`` - Connect to target device using SSH keys (default: ``False``)
|
||||
|
||||
key_file
|
||||
Filename path of the SSH key file to use.
|
||||
- ``key_file`` - Filename path of the SSH key file to use
|
||||
|
||||
allow_agent
|
||||
Enable use of SSH key-agent.
|
||||
- ``allow_agent`` - Enable use of SSH key-agent
|
||||
|
||||
ssh_strict: ``False``
|
||||
Automatically reject unknown SSH host keys (default: ``False``, which means
|
||||
unknown SSH host keys will be accepted).
|
||||
- ``ssh_strict`` - Automatically reject unknown SSH host keys (default:
|
||||
``False``, which means unknown SSH host keys will be accepted)
|
||||
|
||||
system_host_keys: ``False``
|
||||
Load host keys from the user's 'known_hosts' file.
|
||||
- ``system_host_keys`` - Load host keys from the user's "known_hosts" file
|
||||
(default: ``False``)
|
||||
|
||||
alt_host_keys: ``False``
|
||||
If ``True`` host keys will be loaded from the file specified in
|
||||
``alt_key_file``.
|
||||
- ``alt_host_keys`` - If ``True``, host keys will be loaded from the file
|
||||
specified in ``alt_key_file`` (default: ``False``)
|
||||
|
||||
alt_key_file
|
||||
SSH host key file to use (if ``alt_host_keys=True``).
|
||||
- ``alt_key_file`` - SSH host key file to use (if ``alt_host_keys=True``)
|
||||
|
||||
ssh_config_file
|
||||
File name of OpenSSH configuration file.
|
||||
- ``ssh_config_file`` - File name of OpenSSH configuration file
|
||||
|
||||
timeout: ``90``
|
||||
Connection timeout (in seconds).
|
||||
- ``timeout`` - Connection timeout, in seconds (default: ``90``)
|
||||
|
||||
session_timeout: ``60``
|
||||
Set a timeout for parallel requests (in seconds).
|
||||
- ``session_timeout`` - Set a timeout for parallel requests, in seconds
|
||||
(default: ``60``)
|
||||
|
||||
keepalive: ``0``
|
||||
Send SSH keepalive packets at a specific interval, in seconds. Currently
|
||||
defaults to ``0``, for backwards compatibility (it will not attempt to keep
|
||||
the connection alive using the KEEPALIVE packets).
|
||||
- ``keepalive`` - Send SSH keepalive packets at a specific interval, in
|
||||
seconds. Currently defaults to ``0``, for backwards compatibility (it will
|
||||
not attempt to keep the connection alive using the KEEPALIVE packets).
|
||||
|
||||
default_enter: ``\n``
|
||||
Character(s) to send to correspond to enter key (default: ``\n``).
|
||||
- ``default_enter`` - Character(s) to send to correspond to enter key (default:
|
||||
``\\n``)
|
||||
|
||||
response_return: ``\n``
|
||||
Character(s) to use in normalized return data to represent enter key
|
||||
(default: ``\n``)
|
||||
- ``response_return`` - Character(s) to use in normalized return data to
|
||||
represent enter key (default: ``\\n``)
|
||||
|
||||
always_alive: ``True``
|
||||
In certain less dynamic environments, maintaining the remote connection
|
||||
permanently open with the network device is not always beneficial. In that
|
||||
case, the user can select to initialize the connection only when needed, by
|
||||
specifying this field to ``false``.
|
||||
Default: ``true`` (maintains the connection with the remote network device).
|
||||
- ``always_alive`` - In certain less dynamic environments, maintaining the
|
||||
remote connection permanently open with the network device is not always
|
||||
beneficial. In that case, the user can select to initialize the connection
|
||||
only when needed, by setting this option to ``False``. By default this option
|
||||
is set to ``True`` (maintains the connection with the remote network device)
|
||||
|
||||
multiprocessing: ``False``
|
||||
Overrides the :conf_minion:`multiprocessing` option, per proxy minion, as
|
||||
the Netmiko communication channel is mainly SSH.
|
||||
- ``multiprocessing`` - Overrides the :conf_minion:`multiprocessing` option,
|
||||
per proxy minion, as the Netmiko communication channel is mainly SSH
|
||||
(default: ``False``)
|
||||
|
||||
Proxy Pillar Example
|
||||
--------------------
|
||||
|
84
salt/sdb/redis_sdb.py
Normal file
84
salt/sdb/redis_sdb.py
Normal file
@ -0,0 +1,84 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Redis SDB module
|
||||
================
|
||||
|
||||
.. versionadded:: Fluorine
|
||||
|
||||
This module allows access to Redis using an ``sdb://`` URI.
|
||||
|
||||
Like all SDB modules, the Redis module requires a configuration profile to
|
||||
be configured in either the minion or master configuration file. This profile
|
||||
requires very little. For example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
sdb_redis:
|
||||
driver: redis
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
password: pass
|
||||
db: 1
|
||||
|
||||
The ``driver`` refers to the Redis module, all other options are optional.
|
||||
For option details see: https://redis-py.readthedocs.io/en/latest/.
|
||||
|
||||
'''
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
try:
|
||||
import redis
|
||||
HAS_REDIS = True
|
||||
except ImportError:
|
||||
HAS_REDIS = False
|
||||
|
||||
|
||||
__func_alias__ = {
|
||||
'set_': 'set'
|
||||
}
|
||||
__virtualname__ = 'redis'
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Module virtual name.
|
||||
'''
|
||||
if not HAS_REDIS:
|
||||
return (False, 'Please install python-redis to use this SDB module.')
|
||||
return __virtualname__
|
||||
|
||||
|
||||
def set_(key, value, profile=None):
|
||||
'''
|
||||
Set a value into the Redis SDB.
|
||||
'''
|
||||
if not profile:
|
||||
return False
|
||||
redis_kwargs = profile.copy()
|
||||
redis_kwargs.pop('driver')
|
||||
redis_conn = redis.StrictRedis(**redis_kwargs)
|
||||
return redis_conn.set(key, value)
|
||||
|
||||
|
||||
def get(key, profile=None):
|
||||
'''
|
||||
Get a value from the Redis SDB.
|
||||
'''
|
||||
if not profile:
|
||||
return False
|
||||
redis_kwargs = profile.copy()
|
||||
redis_kwargs.pop('driver')
|
||||
redis_conn = redis.StrictRedis(**redis_kwargs)
|
||||
return redis_conn.get(key)
|
||||
|
||||
|
||||
def delete(key, profile=None):
|
||||
'''
|
||||
Delete a key from the Redis SDB.
|
||||
'''
|
||||
if not profile:
|
||||
return False
|
||||
redis_kwargs = profile.copy()
|
||||
redis_kwargs.pop('driver')
|
||||
redis_conn = redis.StrictRedis(**redis_kwargs)
|
||||
return redis_conn.get(key)
|
@ -33,8 +33,23 @@
|
||||
<model type='{{ nic.model }}'/>
|
||||
</interface>
|
||||
{% endfor %}
|
||||
{% if enable_vnc %}
|
||||
<graphics type='vnc' listen='0.0.0.0' autoport='yes' />
|
||||
{% if graphics %}
|
||||
<graphics type='{{ graphics.type }}'
|
||||
{% if graphics.listen.address %}
|
||||
listen='{{ graphics.listen.address }}'
|
||||
{% endif %}
|
||||
{% if graphics.port %}
|
||||
port='{{ graphics.port }}'
|
||||
{% endif %}
|
||||
{% if graphics.type == 'spice' and graphics.tls_port %}
|
||||
tlsPort='{{ graphics.tls_port }}'
|
||||
{% endif %}
|
||||
autoport='{{ 'no' if graphics.port or graphics.tls_port else 'yes' }}'>
|
||||
<listen type='{{ graphics.listen.type }}'
|
||||
{% if graphics.listen.address %}
|
||||
address='{{ graphics.listen.address }}'
|
||||
{% endif %}/>
|
||||
</graphics>
|
||||
{% endif %}
|
||||
{% if serial_type == 'pty' %}
|
||||
<serial type='pty'>
|
||||
|
@ -17,6 +17,7 @@ Utils for the NAPALM modules and proxy.
|
||||
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import, unicode_literals, print_function
|
||||
import copy
|
||||
import traceback
|
||||
import logging
|
||||
import importlib
|
||||
@ -26,6 +27,7 @@ from functools import wraps
|
||||
from salt.ext import six as six
|
||||
import salt.output
|
||||
import salt.utils.platform
|
||||
import salt.utils.args
|
||||
|
||||
# Import third party libs
|
||||
try:
|
||||
@ -93,14 +95,14 @@ def virtual(opts, virtualname, filename):
|
||||
'''
|
||||
Returns the __virtual__.
|
||||
'''
|
||||
if ((HAS_NAPALM and NAPALM_MAJOR >= 2) or HAS_NAPALM_BASE) and (is_proxy(opts) or is_minion(opts)):
|
||||
if (HAS_NAPALM and NAPALM_MAJOR >= 2) or HAS_NAPALM_BASE:
|
||||
return virtualname
|
||||
else:
|
||||
return (
|
||||
False,
|
||||
(
|
||||
'"{vname}"" {filename} cannot be loaded: '
|
||||
'NAPALM is not installed or not running in a (proxy) minion'
|
||||
'NAPALM is not installed: ``pip install napalm``'
|
||||
).format(
|
||||
vname=virtualname,
|
||||
filename='({filename})'.format(filename=filename)
|
||||
@ -255,15 +257,12 @@ def get_device_opts(opts, salt_obj=None):
|
||||
'''
|
||||
network_device = {}
|
||||
# by default, look in the proxy config details
|
||||
device_dict = opts.get('proxy', {}) or opts.get('napalm', {})
|
||||
device_dict = opts.get('proxy', {}) if is_proxy(opts) else opts.get('napalm', {})
|
||||
if opts.get('proxy') or opts.get('napalm'):
|
||||
opts['multiprocessing'] = device_dict.get('multiprocessing', False)
|
||||
# Most NAPALM drivers are SSH-based, so multiprocessing should default to False.
|
||||
# But the user can be allows one to have a different value for the multiprocessing, which will
|
||||
# override the opts.
|
||||
if salt_obj and not device_dict:
|
||||
# get the connection details from the opts
|
||||
device_dict = salt_obj['config.merge']('napalm')
|
||||
if not device_dict:
|
||||
# still not able to setup
|
||||
log.error('Incorrect minion config. Please specify at least the napalm driver name!')
|
||||
@ -367,11 +366,12 @@ def proxy_napalm_wrap(func):
|
||||
# the execution modules will make use of this variable from now on
|
||||
# previously they were accessing the device properties through the __proxy__ object
|
||||
always_alive = opts.get('proxy', {}).get('always_alive', True)
|
||||
if salt.utils.platform.is_proxy() and always_alive:
|
||||
# if it is running in a proxy and it's using the default always alive behaviour,
|
||||
# will get the cached copy of the network device
|
||||
if is_proxy(opts) and always_alive:
|
||||
# if it is running in a NAPALM Proxy and it's using the default
|
||||
# always alive behaviour, will get the cached copy of the network
|
||||
# device object which should preserve the connection.
|
||||
wrapped_global_namespace['napalm_device'] = proxy['napalm.get_device']()
|
||||
elif salt.utils.platform.is_proxy() and not always_alive:
|
||||
elif is_proxy(opts) and not always_alive:
|
||||
# if still proxy, but the user does not want the SSH session always alive
|
||||
# get a new device instance
|
||||
# which establishes a new connection
|
||||
@ -398,10 +398,36 @@ def proxy_napalm_wrap(func):
|
||||
# otherwise we risk to open multiple sessions
|
||||
wrapped_global_namespace['napalm_device'] = kwargs['inherit_napalm_device']
|
||||
else:
|
||||
# if no proxy
|
||||
# if not a NAPLAM proxy
|
||||
# thus it is running on a regular minion, directly on the network device
|
||||
# or another flavour of Minion from where we can invoke arbitrary
|
||||
# NAPALM commands
|
||||
# get __salt__ from func_globals
|
||||
log.debug('Not running in a NAPALM Proxy Minion')
|
||||
_salt_obj = wrapped_global_namespace.get('__salt__')
|
||||
napalm_opts = _salt_obj['config.get']('napalm', {})
|
||||
napalm_inventory = _salt_obj['config.get']('napalm_inventory', {})
|
||||
log.debug('NAPALM opts found in the Minion config')
|
||||
log.debug(napalm_opts)
|
||||
clean_kwargs = salt.utils.args.clean_kwargs(**kwargs)
|
||||
napalm_opts.update(clean_kwargs) # no need for deeper merge
|
||||
log.debug('Merging the found opts with the CLI args')
|
||||
log.debug(napalm_opts)
|
||||
host = napalm_opts.get('host') or napalm_opts.get('hostname') or\
|
||||
napalm_opts.get('fqdn') or napalm_opts.get('ip')
|
||||
if host and napalm_inventory and isinstance(napalm_inventory, dict) and\
|
||||
host in napalm_inventory:
|
||||
inventory_opts = napalm_inventory[host]
|
||||
log.debug('Found %s in the NAPALM inventory:', host)
|
||||
log.debug(inventory_opts)
|
||||
napalm_opts.update(inventory_opts)
|
||||
log.debug('Merging the config for %s with the details found in the napalm inventory:', host)
|
||||
log.debug(napalm_opts)
|
||||
opts = copy.deepcopy(opts) # make sure we don't override the original
|
||||
# opts, but just inject the CLI args from the kwargs to into the
|
||||
# object manipulated by ``get_device_opts`` to extract the
|
||||
# connection details, then use then to establish the connection.
|
||||
opts['napalm'] = napalm_opts
|
||||
if 'inherit_napalm_device' not in kwargs or ('inherit_napalm_device' in kwargs and
|
||||
not kwargs['inherit_napalm_device']):
|
||||
# try to open a new connection
|
||||
|
@ -78,6 +78,12 @@ import salt.utils.stringutils
|
||||
import salt.exceptions
|
||||
import salt.version
|
||||
|
||||
if _six.PY2:
|
||||
import concurrent
|
||||
else:
|
||||
concurrent = None
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -259,7 +265,7 @@ def get_tops(extra_mods='', so_mods=''):
|
||||
:return:
|
||||
'''
|
||||
tops = []
|
||||
for mod in [salt, jinja2, yaml, tornado, msgpack, certifi, singledispatch,
|
||||
for mod in [salt, jinja2, yaml, tornado, msgpack, certifi, singledispatch, concurrent,
|
||||
singledispatch_helpers, ssl_match_hostname, markupsafe, backports_abc]:
|
||||
if mod:
|
||||
log.debug('Adding module to the tops: "%s"', mod.__name__)
|
||||
|
@ -89,7 +89,6 @@ import salt.utils.path
|
||||
import salt.utils.platform
|
||||
import salt.utils.stringutils
|
||||
|
||||
|
||||
# Import Third Party Libs
|
||||
from salt.ext import six
|
||||
from salt.ext.six.moves.http_client import BadStatusLine # pylint: disable=E0611
|
||||
@ -119,8 +118,8 @@ def __virtual__():
|
||||
'''
|
||||
if HAS_PYVMOMI:
|
||||
return True
|
||||
else:
|
||||
return False, 'Missing dependency: The salt.utils.vmware module requires pyVmomi.'
|
||||
|
||||
return False, 'Missing dependency: The salt.utils.vmware module requires pyVmomi.'
|
||||
|
||||
|
||||
def esxcli(host, user, pwd, cmd, protocol=None, port=None, esxi_host=None, credstore=None):
|
||||
@ -227,8 +226,8 @@ def _get_service_instance(host, username, password, protocol,
|
||||
log.error('This may mean that a version of PyVmomi EARLIER than 6.0.0.2016.6 is installed.')
|
||||
log.error('We recommend updating to that version or later.')
|
||||
raise
|
||||
except Exception as exc:
|
||||
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
# pyVmomi's SmartConnect() actually raises Exception in some cases.
|
||||
default_msg = 'Could not connect to host \'{0}\'. ' \
|
||||
'Please check the debug log for more information.'.format(host)
|
||||
|
||||
@ -236,8 +235,6 @@ def _get_service_instance(host, username, password, protocol,
|
||||
if (isinstance(exc, vim.fault.HostConnectFault) and
|
||||
'[SSL: CERTIFICATE_VERIFY_FAILED]' in exc.msg) or \
|
||||
'[SSL: CERTIFICATE_VERIFY_FAILED]' in six.text_type(exc):
|
||||
|
||||
import ssl
|
||||
service_instance = SmartConnect(
|
||||
host=host,
|
||||
user=username,
|
||||
@ -251,9 +248,9 @@ def _get_service_instance(host, username, password, protocol,
|
||||
log.exception(exc)
|
||||
err_msg = exc.msg if hasattr(exc, 'msg') else default_msg
|
||||
raise salt.exceptions.VMwareConnectionError(err_msg)
|
||||
except Exception as exc:
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
# pyVmomi's SmartConnect() actually raises Exception in some cases.
|
||||
if 'certificate verify failed' in six.text_type(exc):
|
||||
import ssl
|
||||
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
|
||||
context.verify_mode = ssl.CERT_NONE
|
||||
try:
|
||||
@ -362,7 +359,9 @@ def get_service_instance(host, username=None, password=None, protocol=None,
|
||||
service_instance = GetSi()
|
||||
if service_instance:
|
||||
stub = GetStub()
|
||||
if salt.utils.platform.is_proxy() or (hasattr(stub, 'host') and stub.host != ':'.join([host, six.text_type(port)])):
|
||||
if (salt.utils.platform.is_proxy() or
|
||||
(hasattr(stub, 'host') and
|
||||
stub.host != ':'.join([host, six.text_type(port)]))):
|
||||
# Proxies will fork and mess up the cached service instance.
|
||||
# If this is a proxy or we are connecting to a different host
|
||||
# invalidate the service instance to avoid a potential memory leak
|
||||
@ -432,9 +431,9 @@ def get_new_service_instance_stub(service_instance, path, ns=None,
|
||||
Version of the new stub.
|
||||
Default value is None.
|
||||
'''
|
||||
#For python 2.7.9 and later, the defaul SSL conext has more strict
|
||||
#connection handshaking rule. We may need turn of the hostname checking
|
||||
#and client side cert verification
|
||||
# For python 2.7.9 and later, the default SSL context has more strict
|
||||
# connection handshaking rule. We may need turn off the hostname checking
|
||||
# and the client side cert verification.
|
||||
context = None
|
||||
if sys.version_info[:3] > (2, 7, 8):
|
||||
context = ssl.create_default_context()
|
||||
@ -669,56 +668,54 @@ def get_hardware_grains(service_instance):
|
||||
if get_inventory(service_instance).about.apiType == 'HostAgent':
|
||||
view = service_instance.content.viewManager.CreateContainerView(service_instance.RetrieveContent().rootFolder,
|
||||
[vim.HostSystem], True)
|
||||
if view:
|
||||
if view.view:
|
||||
if len(view.view) > 0:
|
||||
hw_grain_data['manufacturer'] = view.view[0].hardware.systemInfo.vendor
|
||||
hw_grain_data['productname'] = view.view[0].hardware.systemInfo.model
|
||||
if view and view.view:
|
||||
hw_grain_data['manufacturer'] = view.view[0].hardware.systemInfo.vendor
|
||||
hw_grain_data['productname'] = view.view[0].hardware.systemInfo.model
|
||||
|
||||
for _data in view.view[0].hardware.systemInfo.otherIdentifyingInfo:
|
||||
if _data.identifierType.key == 'ServiceTag':
|
||||
hw_grain_data['serialnumber'] = _data.identifierValue
|
||||
for _data in view.view[0].hardware.systemInfo.otherIdentifyingInfo:
|
||||
if _data.identifierType.key == 'ServiceTag':
|
||||
hw_grain_data['serialnumber'] = _data.identifierValue
|
||||
|
||||
hw_grain_data['osfullname'] = view.view[0].summary.config.product.fullName
|
||||
hw_grain_data['osmanufacturer'] = view.view[0].summary.config.product.vendor
|
||||
hw_grain_data['osrelease'] = view.view[0].summary.config.product.version
|
||||
hw_grain_data['osbuild'] = view.view[0].summary.config.product.build
|
||||
hw_grain_data['os_family'] = view.view[0].summary.config.product.name
|
||||
hw_grain_data['os'] = view.view[0].summary.config.product.name
|
||||
hw_grain_data['mem_total'] = view.view[0].hardware.memorySize /1024/1024
|
||||
hw_grain_data['biosversion'] = view.view[0].hardware.biosInfo.biosVersion
|
||||
hw_grain_data['biosreleasedate'] = view.view[0].hardware.biosInfo.releaseDate.date().strftime('%m/%d/%Y')
|
||||
hw_grain_data['cpu_model'] = view.view[0].hardware.cpuPkg[0].description
|
||||
hw_grain_data['kernel'] = view.view[0].summary.config.product.productLineId
|
||||
hw_grain_data['num_cpu_sockets'] = view.view[0].hardware.cpuInfo.numCpuPackages
|
||||
hw_grain_data['num_cpu_cores'] = view.view[0].hardware.cpuInfo.numCpuCores
|
||||
hw_grain_data['num_cpus'] = hw_grain_data['num_cpu_sockets'] * hw_grain_data['num_cpu_cores']
|
||||
hw_grain_data['ip_interfaces'] = {}
|
||||
hw_grain_data['ip4_interfaces'] = {}
|
||||
hw_grain_data['ip6_interfaces'] = {}
|
||||
hw_grain_data['hwaddr_interfaces'] = {}
|
||||
for _vnic in view.view[0].configManager.networkSystem.networkConfig.vnic:
|
||||
hw_grain_data['ip_interfaces'][_vnic.device] = []
|
||||
hw_grain_data['ip4_interfaces'][_vnic.device] = []
|
||||
hw_grain_data['ip6_interfaces'][_vnic.device] = []
|
||||
hw_grain_data['osfullname'] = view.view[0].summary.config.product.fullName
|
||||
hw_grain_data['osmanufacturer'] = view.view[0].summary.config.product.vendor
|
||||
hw_grain_data['osrelease'] = view.view[0].summary.config.product.version
|
||||
hw_grain_data['osbuild'] = view.view[0].summary.config.product.build
|
||||
hw_grain_data['os_family'] = view.view[0].summary.config.product.name
|
||||
hw_grain_data['os'] = view.view[0].summary.config.product.name
|
||||
hw_grain_data['mem_total'] = view.view[0].hardware.memorySize /1024/1024
|
||||
hw_grain_data['biosversion'] = view.view[0].hardware.biosInfo.biosVersion
|
||||
hw_grain_data['biosreleasedate'] = view.view[0].hardware.biosInfo.releaseDate.date().strftime('%m/%d/%Y')
|
||||
hw_grain_data['cpu_model'] = view.view[0].hardware.cpuPkg[0].description
|
||||
hw_grain_data['kernel'] = view.view[0].summary.config.product.productLineId
|
||||
hw_grain_data['num_cpu_sockets'] = view.view[0].hardware.cpuInfo.numCpuPackages
|
||||
hw_grain_data['num_cpu_cores'] = view.view[0].hardware.cpuInfo.numCpuCores
|
||||
hw_grain_data['num_cpus'] = hw_grain_data['num_cpu_sockets'] * hw_grain_data['num_cpu_cores']
|
||||
hw_grain_data['ip_interfaces'] = {}
|
||||
hw_grain_data['ip4_interfaces'] = {}
|
||||
hw_grain_data['ip6_interfaces'] = {}
|
||||
hw_grain_data['hwaddr_interfaces'] = {}
|
||||
for _vnic in view.view[0].configManager.networkSystem.networkConfig.vnic:
|
||||
hw_grain_data['ip_interfaces'][_vnic.device] = []
|
||||
hw_grain_data['ip4_interfaces'][_vnic.device] = []
|
||||
hw_grain_data['ip6_interfaces'][_vnic.device] = []
|
||||
|
||||
hw_grain_data['ip_interfaces'][_vnic.device].append(_vnic.spec.ip.ipAddress)
|
||||
hw_grain_data['ip4_interfaces'][_vnic.device].append(_vnic.spec.ip.ipAddress)
|
||||
if _vnic.spec.ip.ipV6Config:
|
||||
hw_grain_data['ip6_interfaces'][_vnic.device].append(_vnic.spec.ip.ipV6Config.ipV6Address)
|
||||
hw_grain_data['hwaddr_interfaces'][_vnic.device] = _vnic.spec.mac
|
||||
hw_grain_data['host'] = view.view[0].configManager.networkSystem.dnsConfig.hostName
|
||||
hw_grain_data['domain'] = view.view[0].configManager.networkSystem.dnsConfig.domainName
|
||||
hw_grain_data['fqdn'] = '{0}{1}{2}'.format(
|
||||
view.view[0].configManager.networkSystem.dnsConfig.hostName,
|
||||
('.' if view.view[0].configManager.networkSystem.dnsConfig.domainName else ''),
|
||||
view.view[0].configManager.networkSystem.dnsConfig.domainName)
|
||||
hw_grain_data['ip_interfaces'][_vnic.device].append(_vnic.spec.ip.ipAddress)
|
||||
hw_grain_data['ip4_interfaces'][_vnic.device].append(_vnic.spec.ip.ipAddress)
|
||||
if _vnic.spec.ip.ipV6Config:
|
||||
hw_grain_data['ip6_interfaces'][_vnic.device].append(_vnic.spec.ip.ipV6Config.ipV6Address)
|
||||
hw_grain_data['hwaddr_interfaces'][_vnic.device] = _vnic.spec.mac
|
||||
hw_grain_data['host'] = view.view[0].configManager.networkSystem.dnsConfig.hostName
|
||||
hw_grain_data['domain'] = view.view[0].configManager.networkSystem.dnsConfig.domainName
|
||||
hw_grain_data['fqdn'] = '{0}{1}{2}'.format(
|
||||
view.view[0].configManager.networkSystem.dnsConfig.hostName,
|
||||
('.' if view.view[0].configManager.networkSystem.dnsConfig.domainName else ''),
|
||||
view.view[0].configManager.networkSystem.dnsConfig.domainName)
|
||||
|
||||
for _pnic in view.view[0].configManager.networkSystem.networkInfo.pnic:
|
||||
hw_grain_data['hwaddr_interfaces'][_pnic.device] = _pnic.mac
|
||||
for _pnic in view.view[0].configManager.networkSystem.networkInfo.pnic:
|
||||
hw_grain_data['hwaddr_interfaces'][_pnic.device] = _pnic.mac
|
||||
|
||||
hw_grain_data['timezone'] = view.view[0].configManager.dateTimeSystem.dateTimeInfo.timeZone.name
|
||||
view = None
|
||||
hw_grain_data['timezone'] = view.view[0].configManager.dateTimeSystem.dateTimeInfo.timeZone.name
|
||||
view = None
|
||||
return hw_grain_data
|
||||
|
||||
|
||||
@ -947,9 +944,9 @@ def get_mors_with_properties(service_instance, object_type, property_list=None,
|
||||
content = get_content(*content_args, **content_kwargs)
|
||||
except BadStatusLine:
|
||||
content = get_content(*content_args, **content_kwargs)
|
||||
except IOError as e:
|
||||
if e.errno != errno.EPIPE:
|
||||
raise e
|
||||
except IOError as exc:
|
||||
if exc.errno != errno.EPIPE:
|
||||
raise exc
|
||||
content = get_content(*content_args, **content_kwargs)
|
||||
|
||||
object_list = []
|
||||
@ -1029,6 +1026,8 @@ def get_network_adapter_type(adapter_type):
|
||||
elif adapter_type == 'e1000e':
|
||||
return vim.vm.device.VirtualE1000e()
|
||||
|
||||
raise ValueError('An unknown network adapter object type name.')
|
||||
|
||||
|
||||
def get_network_adapter_object_type(adapter_object):
|
||||
'''
|
||||
@ -1048,6 +1047,8 @@ def get_network_adapter_object_type(adapter_object):
|
||||
if isinstance(adapter_object, vim.vm.device.VirtualE1000):
|
||||
return 'e1000'
|
||||
|
||||
raise ValueError('An unknown network adapter object type.')
|
||||
|
||||
|
||||
def get_dvss(dc_ref, dvs_names=None, get_all_dvss=False):
|
||||
'''
|
||||
@ -1223,8 +1224,8 @@ def get_dvportgroups(parent_ref, portgroup_names=None,
|
||||
get_all_portgroups
|
||||
Return all portgroups in the parent. Default is False.
|
||||
'''
|
||||
if not (isinstance(parent_ref, vim.Datacenter) or
|
||||
isinstance(parent_ref, vim.DistributedVirtualSwitch)):
|
||||
if not (isinstance(parent_ref,
|
||||
(vim.Datacenter, vim.DistributedVirtualSwitch))):
|
||||
raise salt.exceptions.ArgumentValueError(
|
||||
'Parent has to be either a datacenter, '
|
||||
'or a distributed virtual switch')
|
||||
@ -1554,7 +1555,7 @@ def add_license(service_instance, key, description, license_manager=None):
|
||||
label.value = description
|
||||
log.debug('Adding license \'%s\'', description)
|
||||
try:
|
||||
license = license_manager.AddLicense(key, [label])
|
||||
vmware_license = license_manager.AddLicense(key, [label])
|
||||
except vim.fault.NoPermission as exc:
|
||||
log.exception(exc)
|
||||
raise salt.exceptions.VMwareApiError(
|
||||
@ -1566,7 +1567,7 @@ def add_license(service_instance, key, description, license_manager=None):
|
||||
except vmodl.RuntimeFault as exc:
|
||||
log.exception(exc)
|
||||
raise salt.exceptions.VMwareRuntimeError(exc.msg)
|
||||
return license
|
||||
return vmware_license
|
||||
|
||||
|
||||
def get_assigned_licenses(service_instance, entity_ref=None, entity_name=None,
|
||||
@ -1709,9 +1710,10 @@ def assign_license(service_instance, license_key, license_name,
|
||||
|
||||
log.trace('Assigning license to \'%s\'', entity_name)
|
||||
try:
|
||||
license = license_assignment_manager.UpdateAssignedLicense(
|
||||
vmware_license = license_assignment_manager.UpdateAssignedLicense(
|
||||
entity_id,
|
||||
license_key)
|
||||
license_key,
|
||||
license_name)
|
||||
except vim.fault.NoPermission as exc:
|
||||
log.exception(exc)
|
||||
raise salt.exceptions.VMwareApiError(
|
||||
@ -1723,7 +1725,7 @@ def assign_license(service_instance, license_key, license_name,
|
||||
except vmodl.RuntimeFault as exc:
|
||||
log.exception(exc)
|
||||
raise salt.exceptions.VMwareRuntimeError(exc.msg)
|
||||
return license
|
||||
return vmware_license
|
||||
|
||||
|
||||
def list_datacenters(service_instance):
|
||||
@ -1836,7 +1838,7 @@ def get_cluster(dc_ref, cluster):
|
||||
container_ref=dc_ref,
|
||||
property_list=['name'],
|
||||
traversal_spec=traversal_spec)
|
||||
if i['name'] == cluster]
|
||||
if i['name'] == cluster]
|
||||
if not items:
|
||||
raise salt.exceptions.VMwareObjectRetrievalError(
|
||||
'Cluster \'{0}\' was not found in datacenter '
|
||||
@ -2189,7 +2191,8 @@ def _get_partition_info(storage_system, device_path):
|
||||
return partition_infos[0]
|
||||
|
||||
|
||||
def _get_new_computed_partition_spec(hostname, storage_system, device_path,
|
||||
def _get_new_computed_partition_spec(storage_system,
|
||||
device_path,
|
||||
partition_info):
|
||||
'''
|
||||
Computes the new disk partition info when adding a new vmfs partition that
|
||||
@ -2198,7 +2201,7 @@ def _get_new_computed_partition_spec(hostname, storage_system, device_path,
|
||||
'''
|
||||
log.trace('Adding a partition at the end of the disk and getting the new '
|
||||
'computed partition spec')
|
||||
#TODO implement support for multiple partitions
|
||||
# TODO implement support for multiple partitions
|
||||
# We support adding a partition add the end of the disk with partitions
|
||||
free_partitions = [p for p in partition_info.layout.partition
|
||||
if p.type == 'none']
|
||||
@ -2282,7 +2285,10 @@ def create_vmfs_datastore(host_ref, datastore_name, disk_ref,
|
||||
target_disk.devicePath)
|
||||
log.trace('partition_info = %s', partition_info)
|
||||
new_partition_number, partition_spec = _get_new_computed_partition_spec(
|
||||
hostname, storage_system, target_disk.devicePath, partition_info)
|
||||
storage_system,
|
||||
target_disk.devicePath,
|
||||
partition_info
|
||||
)
|
||||
spec = vim.VmfsDatastoreCreateSpec(
|
||||
vmfs=vim.HostVmfsSpec(
|
||||
majorVersion=vmfs_major_version,
|
||||
@ -2355,7 +2361,6 @@ def remove_datastore(service_instance, datastore_ref):
|
||||
datastore_ref, ['host', 'info', 'name'])
|
||||
ds_name = ds_props['name']
|
||||
log.debug('Removing datastore \'%s\'', ds_name)
|
||||
ds_info = ds_props['info']
|
||||
ds_hosts = ds_props.get('host')
|
||||
if not ds_hosts:
|
||||
raise salt.exceptions.VMwareApiError(
|
||||
@ -2417,7 +2422,6 @@ def get_hosts(service_instance, datacenter_name=None, host_names=None,
|
||||
if cluster_name:
|
||||
# Retrieval to test if cluster exists. Cluster existence only makes
|
||||
# sense if the datacenter has been specified
|
||||
cluster = get_cluster(start_point, cluster_name)
|
||||
properties.append('parent')
|
||||
|
||||
# Search for the objects
|
||||
@ -2469,7 +2473,6 @@ def _get_scsi_address_to_lun_key_map(service_instance,
|
||||
hostname
|
||||
Name of the host. Default is None.
|
||||
'''
|
||||
map = {}
|
||||
if not hostname:
|
||||
hostname = get_managed_object_name(host_ref)
|
||||
if not storage_system:
|
||||
@ -2582,8 +2585,8 @@ def get_scsi_address_to_lun_map(host_ref, storage_system=None, hostname=None):
|
||||
if not storage_system:
|
||||
storage_system = get_storage_system(si, host_ref, hostname)
|
||||
lun_ids_to_scsi_addr_map = \
|
||||
_get_scsi_address_to_lun_key_map(si, host_ref, storage_system,
|
||||
hostname)
|
||||
_get_scsi_address_to_lun_key_map(si, host_ref, storage_system,
|
||||
hostname)
|
||||
luns_to_key_map = {d.key: d for d in
|
||||
get_all_luns(host_ref, storage_system, hostname)}
|
||||
return {scsi_addr: luns_to_key_map[lun_key] for scsi_addr, lun_key in
|
||||
@ -2834,19 +2837,18 @@ def _check_disks_in_diskgroup(disk_group, cache_disk_id, capacity_disk_ids):
|
||||
raise salt.exceptions.ArgumentValueError(
|
||||
'Incorrect diskgroup cache disk; got id: \'{0}\'; expected id: '
|
||||
'\'{1}\''.format(disk_group.ssd.canonicalName, cache_disk_id))
|
||||
if sorted([d.canonicalName for d in disk_group.nonSsd]) != \
|
||||
sorted(capacity_disk_ids):
|
||||
|
||||
non_ssd_disks = [d.canonicalName for d in disk_group.nonSsd]
|
||||
if sorted(non_ssd_disks) != sorted(capacity_disk_ids):
|
||||
raise salt.exceptions.ArgumentValueError(
|
||||
'Incorrect capacity disks; got ids: \'{0}\'; expected ids: \'{1}\''
|
||||
''.format(sorted([d.canonicalName for d in disk_group.nonSsd]),
|
||||
''.format(sorted(non_ssd_disks),
|
||||
sorted(capacity_disk_ids)))
|
||||
log.trace('Checked disks in diskgroup with cache disk id \'%s\'',
|
||||
cache_disk_id)
|
||||
return True
|
||||
|
||||
|
||||
#TODO Support host caches on multiple datastores
|
||||
# TODO Support host caches on multiple datastores
|
||||
def get_host_cache(host_ref, host_cache_manager=None):
|
||||
'''
|
||||
Returns a vim.HostScsiDisk if the host cache is configured on the specified
|
||||
@ -2887,7 +2889,7 @@ def get_host_cache(host_ref, host_cache_manager=None):
|
||||
return results['cacheConfigurationInfo'][0]
|
||||
|
||||
|
||||
#TODO Support host caches on multiple datastores
|
||||
# TODO Support host caches on multiple datastores
|
||||
def configure_host_cache(host_ref, datastore_ref, swap_size_MiB,
|
||||
host_cache_manager=None):
|
||||
'''
|
||||
@ -3222,8 +3224,9 @@ def get_vm_by_property(service_instance, name, datacenter=None, vm_properties=No
|
||||
if not vm_formatted:
|
||||
raise salt.exceptions.VMwareObjectRetrievalError('The virtual machine was not found.')
|
||||
elif len(vm_formatted) > 1:
|
||||
raise salt.exceptions.VMwareMultipleObjectsError('Multiple virtual machines were found with the '
|
||||
'same name, please specify a container.')
|
||||
raise salt.exceptions.VMwareMultipleObjectsError(' '.join([
|
||||
'Multiple virtual machines were found with the'
|
||||
'same name, please specify a container.']))
|
||||
return vm_formatted[0]
|
||||
|
||||
|
||||
@ -3250,13 +3253,15 @@ def get_folder(service_instance, datacenter, placement, base_vm_name=None):
|
||||
if 'parent' in vm_props:
|
||||
folder_object = vm_props['parent']
|
||||
else:
|
||||
raise salt.exceptions.VMwareObjectRetrievalError('The virtual machine parent '
|
||||
'object is not defined')
|
||||
raise salt.exceptions.VMwareObjectRetrievalError(' '.join([
|
||||
'The virtual machine parent',
|
||||
'object is not defined']))
|
||||
elif 'folder' in placement:
|
||||
folder_objects = salt.utils.vmware.get_folders(service_instance, [placement['folder']], datacenter)
|
||||
if len(folder_objects) > 1:
|
||||
raise salt.exceptions.VMwareMultipleObjectsError('Multiple instances are available of the '
|
||||
'specified folder {0}'.format(placement['folder']))
|
||||
raise salt.exceptions.VMwareMultipleObjectsError(' '.join([
|
||||
'Multiple instances are available of the',
|
||||
'specified folder {0}'.format(placement['folder'])]))
|
||||
folder_object = folder_objects[0]
|
||||
elif datacenter:
|
||||
datacenter_object = salt.utils.vmware.get_datacenter(service_instance, datacenter)
|
||||
@ -3286,10 +3291,13 @@ def get_placement(service_instance, datacenter, placement=None):
|
||||
if 'host' in placement:
|
||||
host_objects = get_hosts(service_instance, datacenter_name=datacenter, host_names=[placement['host']])
|
||||
if not host_objects:
|
||||
raise salt.exceptions.VMwareObjectRetrievalError('The specified host {0} cannot be found.'.format(placement['host']))
|
||||
raise salt.exceptions.VMwareObjectRetrievalError(' '.join([
|
||||
'The specified host',
|
||||
'{0} cannot be found.'.format(placement['host'])]))
|
||||
try:
|
||||
host_props = get_properties_of_managed_object(host_objects[0],
|
||||
properties=['resourcePool'])
|
||||
host_props = \
|
||||
get_properties_of_managed_object(host_objects[0],
|
||||
properties=['resourcePool'])
|
||||
resourcepool_object = host_props['resourcePool']
|
||||
except vmodl.query.InvalidProperty:
|
||||
traversal_spec = vmodl.query.PropertyCollector.TraversalSpec(
|
||||
@ -3316,16 +3324,18 @@ def get_placement(service_instance, datacenter, placement=None):
|
||||
[placement['resourcepool']],
|
||||
datacenter_name=datacenter)
|
||||
if len(resourcepool_objects) > 1:
|
||||
raise salt.exceptions.VMwareMultipleObjectsError('Multiple instances are available of the '
|
||||
'specified host {}.'.format(placement['host']))
|
||||
raise salt.exceptions.VMwareMultipleObjectsError(' '.join([
|
||||
'Multiple instances are available of the',
|
||||
'specified host {}.'.format(placement['host'])]))
|
||||
resourcepool_object = resourcepool_objects[0]
|
||||
res_props = get_properties_of_managed_object(resourcepool_object,
|
||||
properties=['parent'])
|
||||
if 'parent' in res_props:
|
||||
placement_object = res_props['parent']
|
||||
else:
|
||||
raise salt.exceptions.VMwareObjectRetrievalError('The resource pool\'s parent '
|
||||
'object is not defined')
|
||||
raise salt.exceptions.VMwareObjectRetrievalError(' '.join([
|
||||
'The resource pool\'s parent',
|
||||
'object is not defined']))
|
||||
elif 'cluster' in placement:
|
||||
datacenter_object = get_datacenter(service_instance, datacenter)
|
||||
cluster_object = get_cluster(datacenter_object, placement['cluster'])
|
||||
@ -3334,12 +3344,14 @@ def get_placement(service_instance, datacenter, placement=None):
|
||||
if 'resourcePool' in clus_props:
|
||||
resourcepool_object = clus_props['resourcePool']
|
||||
else:
|
||||
raise salt.exceptions.VMwareObjectRetrievalError('The cluster\'s resource pool '
|
||||
'object is not defined')
|
||||
raise salt.exceptions.VMwareObjectRetrievalError(' '.join([
|
||||
'The cluster\'s resource pool',
|
||||
'object is not defined']))
|
||||
placement_object = cluster_object
|
||||
else:
|
||||
# We are checking the schema for this object, this exception should never be raised
|
||||
raise salt.exceptions.VMwareObjectRetrievalError('Placement is not defined.')
|
||||
raise salt.exceptions.VMwareObjectRetrievalError(' '.join([
|
||||
'Placement is not defined.']))
|
||||
return (resourcepool_object, placement_object)
|
||||
|
||||
|
||||
@ -3409,8 +3421,9 @@ def power_cycle_vm(virtual_machine, action='on'):
|
||||
try:
|
||||
wait_for_task(task, get_managed_object_name(virtual_machine), task_name)
|
||||
except salt.exceptions.VMwareFileNotFoundError as exc:
|
||||
raise salt.exceptions.VMwarePowerOnError('An error occurred during power '
|
||||
'operation, a file was not found: {0}'.format(exc))
|
||||
raise salt.exceptions.VMwarePowerOnError(' '.join([
|
||||
'An error occurred during power',
|
||||
'operation, a file was not found: {0}'.format(exc)]))
|
||||
return virtual_machine
|
||||
|
||||
|
||||
|
@ -8,7 +8,7 @@ virt execution module unit tests
|
||||
# Import python libs
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
import re
|
||||
import os
|
||||
import datetime
|
||||
|
||||
# Import Salt Testing libs
|
||||
from tests.support.mixins import LoaderModuleMockMixin
|
||||
@ -21,6 +21,7 @@ import salt.modules.virt as virt
|
||||
import salt.modules.config as config
|
||||
from salt._compat import ElementTree as ET
|
||||
import salt.config
|
||||
from salt.exceptions import CommandExecutionError
|
||||
|
||||
# Import third party libs
|
||||
from salt.ext import six
|
||||
@ -50,14 +51,19 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
self.mock_libvirt = LibvirtMock()
|
||||
self.mock_conn = MagicMock()
|
||||
self.mock_libvirt.openAuth.return_value = self.mock_conn
|
||||
self.mock_popen = MagicMock()
|
||||
self.addCleanup(delattr, self, 'mock_libvirt')
|
||||
self.addCleanup(delattr, self, 'mock_conn')
|
||||
self.addCleanup(delattr, self, 'mock_popen')
|
||||
mock_subprocess = MagicMock()
|
||||
mock_subprocess.Popen.return_value = self.mock_popen # pylint: disable=no-member
|
||||
loader_globals = {
|
||||
'__salt__': {
|
||||
'config.get': config.get,
|
||||
'config.option': config.option,
|
||||
},
|
||||
'libvirt': self.mock_libvirt
|
||||
'libvirt': self.mock_libvirt,
|
||||
'subprocess': mock_subprocess
|
||||
}
|
||||
return {virt: loader_globals, config: loader_globals}
|
||||
|
||||
@ -73,11 +79,35 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
# Return state as shutdown
|
||||
mock_domain.info.return_value = [4, 0, 0, 0] # pylint: disable=no-member
|
||||
|
||||
def test_disk_profile_merge(self):
|
||||
'''
|
||||
Test virt._disk_profile() when merging with user-defined disks
|
||||
'''
|
||||
userdisks = [{'name': 'data', 'size': 16384, 'format': 'raw'}]
|
||||
|
||||
disks = virt._disk_profile('default', 'kvm', userdisks, 'myvm', image='/path/to/image')
|
||||
self.assertEqual(
|
||||
[{'name': 'system',
|
||||
'size': 8192,
|
||||
'format': 'qcow2',
|
||||
'model': 'virtio',
|
||||
'filename': 'myvm_system.qcow2',
|
||||
'image': '/path/to/image',
|
||||
'source_file': '/srv/salt-images/myvm_system.qcow2'},
|
||||
{'name': 'data',
|
||||
'size': 16384,
|
||||
'format': 'raw',
|
||||
'model': 'virtio',
|
||||
'filename': 'myvm_data.raw',
|
||||
'source_file': '/srv/salt-images/myvm_data.raw'}],
|
||||
disks
|
||||
)
|
||||
|
||||
def test_boot_default_dev(self):
|
||||
'''
|
||||
Test virt._gen_xml() default boot device
|
||||
'''
|
||||
diskp = virt._disk_profile('default', 'kvm')
|
||||
diskp = virt._disk_profile('default', 'kvm', [], 'hello')
|
||||
nicp = virt._nic_profile('default', 'kvm')
|
||||
xml_data = virt._gen_xml(
|
||||
'hello',
|
||||
@ -94,7 +124,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'''
|
||||
Test virt._gen_xml() custom boot device
|
||||
'''
|
||||
diskp = virt._disk_profile('default', 'kvm')
|
||||
diskp = virt._disk_profile('default', 'kvm', [], 'hello')
|
||||
nicp = virt._nic_profile('default', 'kvm')
|
||||
xml_data = virt._gen_xml(
|
||||
'hello',
|
||||
@ -112,7 +142,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'''
|
||||
Test virt._gen_xml() multiple boot devices
|
||||
'''
|
||||
diskp = virt._disk_profile('default', 'kvm')
|
||||
diskp = virt._disk_profile('default', 'kvm', [], 'hello')
|
||||
nicp = virt._nic_profile('default', 'kvm')
|
||||
xml_data = virt._gen_xml(
|
||||
'hello',
|
||||
@ -131,7 +161,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'''
|
||||
Test virt._gen_xml() serial console
|
||||
'''
|
||||
diskp = virt._disk_profile('default', 'kvm')
|
||||
diskp = virt._disk_profile('default', 'kvm', [], 'hello')
|
||||
nicp = virt._nic_profile('default', 'kvm')
|
||||
xml_data = virt._gen_xml(
|
||||
'hello',
|
||||
@ -151,7 +181,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'''
|
||||
Test virt._gen_xml() telnet console
|
||||
'''
|
||||
diskp = virt._disk_profile('default', 'kvm')
|
||||
diskp = virt._disk_profile('default', 'kvm', [], 'hello')
|
||||
nicp = virt._nic_profile('default', 'kvm')
|
||||
xml_data = virt._gen_xml(
|
||||
'hello',
|
||||
@ -173,7 +203,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'''
|
||||
Test virt._gen_xml() telnet console without any specified port
|
||||
'''
|
||||
diskp = virt._disk_profile('default', 'kvm')
|
||||
diskp = virt._disk_profile('default', 'kvm', [], 'hello')
|
||||
nicp = virt._nic_profile('default', 'kvm')
|
||||
xml_data = virt._gen_xml(
|
||||
'hello',
|
||||
@ -194,7 +224,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'''
|
||||
Test virt._gen_xml() with no serial console
|
||||
'''
|
||||
diskp = virt._disk_profile('default', 'kvm')
|
||||
diskp = virt._disk_profile('default', 'kvm', [], 'hello')
|
||||
nicp = virt._nic_profile('default', 'kvm')
|
||||
xml_data = virt._gen_xml(
|
||||
'hello',
|
||||
@ -214,7 +244,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'''
|
||||
Test virt._gen_xml() with no telnet console
|
||||
'''
|
||||
diskp = virt._disk_profile('default', 'kvm')
|
||||
diskp = virt._disk_profile('default', 'kvm', [], 'hello')
|
||||
nicp = virt._nic_profile('default', 'kvm')
|
||||
xml_data = virt._gen_xml(
|
||||
'hello',
|
||||
@ -230,16 +260,105 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
self.assertEqual(root.find('devices/serial').attrib['type'], 'tcp')
|
||||
self.assertEqual(root.find('devices/console'), None)
|
||||
|
||||
def test_gen_xml_nographics_default(self):
|
||||
'''
|
||||
Test virt._gen_xml() with default no graphics device
|
||||
'''
|
||||
diskp = virt._disk_profile('default', 'kvm', [], 'hello')
|
||||
nicp = virt._nic_profile('default', 'kvm')
|
||||
xml_data = virt._gen_xml(
|
||||
'hello',
|
||||
1,
|
||||
512,
|
||||
diskp,
|
||||
nicp,
|
||||
'kvm'
|
||||
)
|
||||
root = ET.fromstring(xml_data)
|
||||
self.assertIsNone(root.find('devices/graphics'))
|
||||
|
||||
def test_gen_xml_vnc_default(self):
|
||||
'''
|
||||
Test virt._gen_xml() with default vnc graphics device
|
||||
'''
|
||||
diskp = virt._disk_profile('default', 'kvm', [], 'hello')
|
||||
nicp = virt._nic_profile('default', 'kvm')
|
||||
xml_data = virt._gen_xml(
|
||||
'hello',
|
||||
1,
|
||||
512,
|
||||
diskp,
|
||||
nicp,
|
||||
'kvm',
|
||||
graphics={'type': 'vnc', 'port': 1234, 'tlsPort': 5678,
|
||||
'listen': {'type': 'address', 'address': 'myhost'}},
|
||||
)
|
||||
root = ET.fromstring(xml_data)
|
||||
self.assertEqual(root.find('devices/graphics').attrib['type'], 'vnc')
|
||||
self.assertEqual(root.find('devices/graphics').attrib['autoport'], 'no')
|
||||
self.assertEqual(root.find('devices/graphics').attrib['port'], '1234')
|
||||
self.assertFalse('tlsPort' in root.find('devices/graphics').attrib)
|
||||
self.assertEqual(root.find('devices/graphics').attrib['listen'], 'myhost')
|
||||
self.assertEqual(root.find('devices/graphics/listen').attrib['type'], 'address')
|
||||
self.assertEqual(root.find('devices/graphics/listen').attrib['address'], 'myhost')
|
||||
|
||||
def test_gen_xml_spice_default(self):
|
||||
'''
|
||||
Test virt._gen_xml() with default spice graphics device
|
||||
'''
|
||||
diskp = virt._disk_profile('default', 'kvm', [], 'hello')
|
||||
nicp = virt._nic_profile('default', 'kvm')
|
||||
xml_data = virt._gen_xml(
|
||||
'hello',
|
||||
1,
|
||||
512,
|
||||
diskp,
|
||||
nicp,
|
||||
'kvm',
|
||||
graphics={'type': 'spice'},
|
||||
)
|
||||
root = ET.fromstring(xml_data)
|
||||
self.assertEqual(root.find('devices/graphics').attrib['type'], 'spice')
|
||||
self.assertEqual(root.find('devices/graphics').attrib['autoport'], 'yes')
|
||||
self.assertEqual(root.find('devices/graphics').attrib['listen'], '0.0.0.0')
|
||||
self.assertEqual(root.find('devices/graphics/listen').attrib['type'], 'address')
|
||||
self.assertEqual(root.find('devices/graphics/listen').attrib['address'], '0.0.0.0')
|
||||
|
||||
def test_gen_xml_spice(self):
|
||||
'''
|
||||
Test virt._gen_xml() with spice graphics device
|
||||
'''
|
||||
diskp = virt._disk_profile('default', 'kvm', [], 'hello')
|
||||
nicp = virt._nic_profile('default', 'kvm')
|
||||
xml_data = virt._gen_xml(
|
||||
'hello',
|
||||
1,
|
||||
512,
|
||||
diskp,
|
||||
nicp,
|
||||
'kvm',
|
||||
graphics={'type': 'spice', 'port': 1234, 'tls_port': 5678, 'listen': {'type': 'none'}},
|
||||
)
|
||||
root = ET.fromstring(xml_data)
|
||||
self.assertEqual(root.find('devices/graphics').attrib['type'], 'spice')
|
||||
self.assertEqual(root.find('devices/graphics').attrib['autoport'], 'no')
|
||||
self.assertEqual(root.find('devices/graphics').attrib['port'], '1234')
|
||||
self.assertEqual(root.find('devices/graphics').attrib['tlsPort'], '5678')
|
||||
self.assertFalse('listen' in root.find('devices/graphics').attrib)
|
||||
self.assertEqual(root.find('devices/graphics/listen').attrib['type'], 'none')
|
||||
self.assertFalse('address' in root.find('devices/graphics/listen').attrib)
|
||||
|
||||
def test_default_disk_profile_hypervisor_esxi(self):
|
||||
'''
|
||||
Test virt._disk_profile() default ESXi profile
|
||||
'''
|
||||
mock = MagicMock(return_value={})
|
||||
with patch.dict(virt.__salt__, {'config.get': mock}): # pylint: disable=no-member
|
||||
ret = virt._disk_profile('nonexistent', 'esxi')
|
||||
ret = virt._disk_profile('nonexistent', 'vmware')
|
||||
self.assertTrue(len(ret) == 1)
|
||||
self.assertIn('system', ret[0])
|
||||
system = ret[0]['system']
|
||||
found = [disk for disk in ret if disk['name'] == 'system']
|
||||
self.assertTrue(bool(found))
|
||||
system = found[0]
|
||||
self.assertEqual(system['format'], 'vmdk')
|
||||
self.assertEqual(system['model'], 'scsi')
|
||||
self.assertTrue(int(system['size']) >= 1)
|
||||
@ -252,8 +371,9 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
with patch.dict(virt.__salt__, {'config.get': mock}): # pylint: disable=no-member
|
||||
ret = virt._disk_profile('nonexistent', 'kvm')
|
||||
self.assertTrue(len(ret) == 1)
|
||||
self.assertIn('system', ret[0])
|
||||
system = ret[0]['system']
|
||||
found = [disk for disk in ret if disk['name'] == 'system']
|
||||
self.assertTrue(bool(found))
|
||||
system = found[0]
|
||||
self.assertEqual(system['format'], 'qcow2')
|
||||
self.assertEqual(system['model'], 'virtio')
|
||||
self.assertTrue(int(system['size']) >= 1)
|
||||
@ -264,7 +384,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'''
|
||||
mock = MagicMock(return_value={})
|
||||
with patch.dict(virt.__salt__, {'config.get': mock}): # pylint: disable=no-member
|
||||
ret = virt._nic_profile('nonexistent', 'esxi')
|
||||
ret = virt._nic_profile('nonexistent', 'vmware')
|
||||
self.assertTrue(len(ret) == 1)
|
||||
eth0 = ret[0]
|
||||
self.assertEqual(eth0['name'], 'eth0')
|
||||
@ -301,7 +421,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'''
|
||||
Test virt._gen_xml(), KVM default profile case
|
||||
'''
|
||||
diskp = virt._disk_profile('default', 'kvm')
|
||||
diskp = virt._disk_profile('default', 'kvm', [], 'hello')
|
||||
nicp = virt._nic_profile('default', 'kvm')
|
||||
xml_data = virt._gen_xml(
|
||||
'hello',
|
||||
@ -322,7 +442,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
disk = disks[0]
|
||||
root_dir = salt.config.DEFAULT_MINION_OPTS.get('root_dir')
|
||||
self.assertTrue(disk.find('source').attrib['file'].startswith(root_dir))
|
||||
self.assertTrue(os.path.join('hello', 'system') in disk.find('source').attrib['file'])
|
||||
self.assertTrue('hello_system' in disk.find('source').attrib['file'])
|
||||
self.assertEqual(disk.find('target').attrib['dev'], 'vda')
|
||||
self.assertEqual(disk.find('target').attrib['bus'], 'virtio')
|
||||
self.assertEqual(disk.find('driver').attrib['name'], 'qemu')
|
||||
@ -341,17 +461,17 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
|
||||
def test_gen_xml_for_esxi_default_profile(self):
|
||||
'''
|
||||
Test virt._gen_xml(), ESXi default profile case
|
||||
Test virt._gen_xml(), ESXi/vmware default profile case
|
||||
'''
|
||||
diskp = virt._disk_profile('default', 'esxi')
|
||||
nicp = virt._nic_profile('default', 'esxi')
|
||||
diskp = virt._disk_profile('default', 'vmware', [], 'hello')
|
||||
nicp = virt._nic_profile('default', 'vmware')
|
||||
xml_data = virt._gen_xml(
|
||||
'hello',
|
||||
1,
|
||||
512,
|
||||
diskp,
|
||||
nicp,
|
||||
'esxi',
|
||||
'vmware',
|
||||
)
|
||||
root = ET.fromstring(xml_data)
|
||||
self.assertEqual(root.attrib['type'], 'vmware')
|
||||
@ -363,7 +483,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
self.assertEqual(len(disks), 1)
|
||||
disk = disks[0]
|
||||
self.assertTrue('[0]' in disk.find('source').attrib['file'])
|
||||
self.assertTrue(os.path.join('hello', 'system') in disk.find('source').attrib['file'])
|
||||
self.assertTrue('hello_system' in disk.find('source').attrib['file'])
|
||||
self.assertEqual(disk.find('target').attrib['dev'], 'sda')
|
||||
self.assertEqual(disk.find('target').attrib['bus'], 'scsi')
|
||||
self.assertEqual(disk.find('address').attrib['unit'], '0')
|
||||
@ -381,45 +501,31 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
|
||||
def test_gen_xml_for_esxi_custom_profile(self):
|
||||
'''
|
||||
Test virt._gen_xml(), ESXi custom profile case
|
||||
Test virt._gen_xml(), ESXi/vmware custom profile case
|
||||
'''
|
||||
diskp_yaml = '''
|
||||
- first:
|
||||
size: 8192
|
||||
format: vmdk
|
||||
model: scsi
|
||||
pool: datastore1
|
||||
- second:
|
||||
size: 4096
|
||||
format: vmdk
|
||||
model: scsi
|
||||
pool: datastore2
|
||||
'''
|
||||
nicp_yaml = '''
|
||||
- type: bridge
|
||||
name: eth1
|
||||
source: ONENET
|
||||
model: e1000
|
||||
mac: '00:00:00:00:00:00'
|
||||
- name: eth2
|
||||
type: bridge
|
||||
source: TWONET
|
||||
model: e1000
|
||||
mac: '00:00:00:00:00:00'
|
||||
'''
|
||||
with patch('salt.modules.virt._nic_profile') as nic_profile, \
|
||||
patch('salt.modules.virt._disk_profile') as disk_profile:
|
||||
disk_profile.return_value = salt.utils.yaml.safe_load(diskp_yaml)
|
||||
nic_profile.return_value = salt.utils.yaml.safe_load(nicp_yaml)
|
||||
diskp = virt._disk_profile('noeffect', 'esxi')
|
||||
nicp = virt._nic_profile('noeffect', 'esxi')
|
||||
disks = {
|
||||
'noeffect': [
|
||||
{'first': {'size': 8192, 'pool': 'datastore1'}},
|
||||
{'second': {'size': 4096, 'pool': 'datastore2'}}
|
||||
]
|
||||
}
|
||||
nics = {
|
||||
'noeffect': [
|
||||
{'name': 'eth1', 'source': 'ONENET'},
|
||||
{'name': 'eth2', 'source': 'TWONET'}
|
||||
]
|
||||
}
|
||||
with patch.dict(virt.__salt__, # pylint: disable=no-member
|
||||
{'config.get': MagicMock(side_effect=[disks, nics])}):
|
||||
diskp = virt._disk_profile('noeffect', 'vmware', [], 'hello')
|
||||
nicp = virt._nic_profile('noeffect', 'vmware')
|
||||
xml_data = virt._gen_xml(
|
||||
'hello',
|
||||
1,
|
||||
512,
|
||||
diskp,
|
||||
nicp,
|
||||
'esxi',
|
||||
'vmware',
|
||||
)
|
||||
root = ET.fromstring(xml_data)
|
||||
self.assertEqual(root.attrib['type'], 'vmware')
|
||||
@ -433,35 +539,21 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'''
|
||||
Test virt._gen_xml(), KVM custom profile case
|
||||
'''
|
||||
diskp_yaml = '''
|
||||
- first:
|
||||
size: 8192
|
||||
format: qcow2
|
||||
model: virtio
|
||||
pool: /var/lib/images
|
||||
- second:
|
||||
size: 4096
|
||||
format: qcow2
|
||||
model: virtio
|
||||
pool: /var/lib/images
|
||||
'''
|
||||
nicp_yaml = '''
|
||||
- type: bridge
|
||||
name: eth1
|
||||
source: b2
|
||||
model: virtio
|
||||
mac: '00:00:00:00:00:00'
|
||||
- name: eth2
|
||||
type: bridge
|
||||
source: b2
|
||||
model: virtio
|
||||
mac: '00:00:00:00:00:00'
|
||||
'''
|
||||
with patch('salt.modules.virt._nic_profile') as nic_profile, \
|
||||
patch('salt.modules.virt._disk_profile') as disk_profile:
|
||||
disk_profile.return_value = salt.utils.yaml.safe_load(diskp_yaml)
|
||||
nic_profile.return_value = salt.utils.yaml.safe_load(nicp_yaml)
|
||||
diskp = virt._disk_profile('noeffect', 'kvm')
|
||||
disks = {
|
||||
'noeffect': [
|
||||
{'first': {'size': 8192, 'pool': '/var/lib/images'}},
|
||||
{'second': {'size': 4096, 'pool': '/var/lib/images'}}
|
||||
]
|
||||
}
|
||||
nics = {
|
||||
'noeffect': [
|
||||
{'name': 'eth1', 'source': 'b2'},
|
||||
{'name': 'eth2', 'source': 'b2'}
|
||||
]
|
||||
}
|
||||
with patch.dict(virt.__salt__, {'config.get': MagicMock(side_effect=[ # pylint: disable=no-member
|
||||
disks, nics])}):
|
||||
diskp = virt._disk_profile('noeffect', 'kvm', [], 'hello')
|
||||
nicp = virt._nic_profile('noeffect', 'kvm')
|
||||
xml_data = virt._gen_xml(
|
||||
'hello',
|
||||
@ -479,19 +571,68 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
self.assertTrue(len(root.findall('.//disk')) == 2)
|
||||
self.assertTrue(len(root.findall('.//interface')) == 2)
|
||||
|
||||
@patch('salt.modules.virt.pool_info', return_value={'target_path': '/pools/default'})
|
||||
def test_disk_profile_kvm_disk_pool(self, mock_poolinfo):
|
||||
'''
|
||||
Test virt._gen_xml(), KVM case with pools defined.
|
||||
'''
|
||||
disks = {
|
||||
'noeffect': [
|
||||
{'first': {'size': 8192, 'pool': 'default'}},
|
||||
{'second': {'size': 4096}}
|
||||
]
|
||||
}
|
||||
with patch.dict(virt.__salt__, {'config.get': MagicMock(side_effect=[ # pylint: disable=no-member
|
||||
disks, "/default/path/"])}):
|
||||
diskp = virt._disk_profile('noeffect', 'kvm', [], 'hello')
|
||||
|
||||
self.assertEqual(len(diskp), 2)
|
||||
self.assertTrue(diskp[0]['source_file'].startswith('/pools/default/'))
|
||||
self.assertTrue(diskp[1]['source_file'].startswith('/default/path/'))
|
||||
|
||||
@patch('salt.modules.virt.pool_info', return_value={})
|
||||
def test_disk_profile_kvm_disk_pool_notfound(self, mock_poolinfo):
|
||||
'''
|
||||
Test virt._gen_xml(), KVM case with pools defined.
|
||||
'''
|
||||
disks = {
|
||||
'noeffect': [
|
||||
{'first': {'size': 8192, 'pool': 'default'}},
|
||||
]
|
||||
}
|
||||
with patch.dict(virt.__salt__, {'config.get': MagicMock(side_effect=[ # pylint: disable=no-member
|
||||
disks, "/default/path/"])}):
|
||||
with self.assertRaises(CommandExecutionError):
|
||||
virt._disk_profile('noeffect', 'kvm', [], 'hello')
|
||||
|
||||
@patch('salt.modules.virt.pool_info', return_value={'target_path': '/dev/disk/by-path'})
|
||||
def test_disk_profile_kvm_disk_pool_invalid(self, mock_poolinfo):
|
||||
'''
|
||||
Test virt._gen_xml(), KVM case with pools defined.
|
||||
'''
|
||||
disks = {
|
||||
'noeffect': [
|
||||
{'first': {'size': 8192, 'pool': 'default'}},
|
||||
]
|
||||
}
|
||||
with patch.dict(virt.__salt__, {'config.get': MagicMock(side_effect=[ # pylint: disable=no-member
|
||||
disks, "/default/path/"])}):
|
||||
with self.assertRaises(CommandExecutionError):
|
||||
virt._disk_profile('noeffect', 'kvm', [], 'hello')
|
||||
|
||||
def test_controller_for_esxi(self):
|
||||
'''
|
||||
Test virt._gen_xml() generated device controller for ESXi
|
||||
Test virt._gen_xml() generated device controller for ESXi/vmware
|
||||
'''
|
||||
diskp = virt._disk_profile('default', 'esxi')
|
||||
nicp = virt._nic_profile('default', 'esxi')
|
||||
diskp = virt._disk_profile('default', 'vmware', [], 'hello')
|
||||
nicp = virt._nic_profile('default', 'vmware')
|
||||
xml_data = virt._gen_xml(
|
||||
'hello',
|
||||
1,
|
||||
512,
|
||||
diskp,
|
||||
nicp,
|
||||
'esxi'
|
||||
'vmware'
|
||||
)
|
||||
root = ET.fromstring(xml_data)
|
||||
controllers = root.findall('.//devices/controller')
|
||||
@ -503,7 +644,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'''
|
||||
Test virt._gen_xml() generated device controller for KVM
|
||||
'''
|
||||
diskp = virt._disk_profile('default', 'kvm')
|
||||
diskp = virt._disk_profile('default', 'kvm', [], 'hello')
|
||||
nicp = virt._nic_profile('default', 'kvm')
|
||||
xml_data = virt._gen_xml(
|
||||
'hello',
|
||||
@ -608,11 +749,130 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
self.assertEqual('bridge', nic['type'])
|
||||
self.assertEqual('ac:de:48:b6:8b:59', nic['mac'])
|
||||
|
||||
@patch('subprocess.Popen')
|
||||
@patch('subprocess.Popen.communicate', return_value="")
|
||||
def test_get_disks(self, mock_communicate, mock_popen):
|
||||
def test_parse_qemu_img_info(self):
|
||||
'''
|
||||
Test virt.get_discs()
|
||||
Make sure that qemu-img info output is properly parsed
|
||||
'''
|
||||
qemu_infos = '''[{
|
||||
"snapshots": [
|
||||
{
|
||||
"vm-clock-nsec": 0,
|
||||
"name": "first-snap",
|
||||
"date-sec": 1528877587,
|
||||
"date-nsec": 380589000,
|
||||
"vm-clock-sec": 0,
|
||||
"id": "1",
|
||||
"vm-state-size": 1234
|
||||
},
|
||||
{
|
||||
"vm-clock-nsec": 0,
|
||||
"name": "second snap",
|
||||
"date-sec": 1528877592,
|
||||
"date-nsec": 933509000,
|
||||
"vm-clock-sec": 0,
|
||||
"id": "2",
|
||||
"vm-state-size": 4567
|
||||
}
|
||||
],
|
||||
"virtual-size": 25769803776,
|
||||
"filename": "/disks/test.qcow2",
|
||||
"cluster-size": 65536,
|
||||
"format": "qcow2",
|
||||
"actual-size": 217088,
|
||||
"format-specific": {
|
||||
"type": "qcow2",
|
||||
"data": {
|
||||
"compat": "1.1",
|
||||
"lazy-refcounts": false,
|
||||
"refcount-bits": 16,
|
||||
"corrupt": false
|
||||
}
|
||||
},
|
||||
"full-backing-filename": "/disks/mybacking.qcow2",
|
||||
"backing-filename": "mybacking.qcow2",
|
||||
"dirty-flag": false
|
||||
},
|
||||
{
|
||||
"virtual-size": 25769803776,
|
||||
"filename": "/disks/mybacking.qcow2",
|
||||
"cluster-size": 65536,
|
||||
"format": "qcow2",
|
||||
"actual-size": 393744384,
|
||||
"format-specific": {
|
||||
"type": "qcow2",
|
||||
"data": {
|
||||
"compat": "1.1",
|
||||
"lazy-refcounts": false,
|
||||
"refcount-bits": 16,
|
||||
"corrupt": false
|
||||
}
|
||||
},
|
||||
"full-backing-filename": "/disks/root.qcow2",
|
||||
"backing-filename": "root.qcow2",
|
||||
"dirty-flag": false
|
||||
},
|
||||
{
|
||||
"virtual-size": 25769803776,
|
||||
"filename": "/disks/root.qcow2",
|
||||
"cluster-size": 65536,
|
||||
"format": "qcow2",
|
||||
"actual-size": 196872192,
|
||||
"format-specific": {
|
||||
"type": "qcow2",
|
||||
"data": {
|
||||
"compat": "1.1",
|
||||
"lazy-refcounts": false,
|
||||
"refcount-bits": 16,
|
||||
"corrupt": false
|
||||
}
|
||||
},
|
||||
"dirty-flag": false
|
||||
}]'''
|
||||
|
||||
self.assertEqual(
|
||||
{
|
||||
'file': '/disks/test.qcow2',
|
||||
'file format': 'qcow2',
|
||||
'backing file': {
|
||||
'file': '/disks/mybacking.qcow2',
|
||||
'file format': 'qcow2',
|
||||
'disk size': 393744384,
|
||||
'virtual size': 25769803776,
|
||||
'cluster size': 65536,
|
||||
'backing file': {
|
||||
'file': '/disks/root.qcow2',
|
||||
'file format': 'qcow2',
|
||||
'disk size': 196872192,
|
||||
'virtual size': 25769803776,
|
||||
'cluster size': 65536,
|
||||
}
|
||||
},
|
||||
'disk size': 217088,
|
||||
'virtual size': 25769803776,
|
||||
'cluster size': 65536,
|
||||
'snapshots': [
|
||||
{
|
||||
'id': '1',
|
||||
'tag': 'first-snap',
|
||||
'vmsize': 1234,
|
||||
'date': datetime.datetime.fromtimestamp(
|
||||
float("{}.{}".format(1528877587, 380589000))).isoformat(),
|
||||
'vmclock': '00:00:00'
|
||||
},
|
||||
{
|
||||
'id': '2',
|
||||
'tag': 'second snap',
|
||||
'vmsize': 4567,
|
||||
'date': datetime.datetime.fromtimestamp(
|
||||
float("{}.{}".format(1528877592, 933509000))).isoformat(),
|
||||
'vmclock': '00:00:00'
|
||||
}
|
||||
],
|
||||
}, virt._parse_qemu_img_info(qemu_infos))
|
||||
|
||||
def test_get_disks(self):
|
||||
'''
|
||||
Test virt.get_disks()
|
||||
'''
|
||||
xml = '''<domain type='kvm' id='7'>
|
||||
<name>test-vm</name>
|
||||
@ -633,20 +893,58 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'''
|
||||
self.set_mock_vm("test-vm", xml)
|
||||
|
||||
qemu_infos = '''[{
|
||||
"virtual-size": 25769803776,
|
||||
"filename": "/disks/test.qcow2",
|
||||
"cluster-size": 65536,
|
||||
"format": "qcow2",
|
||||
"actual-size": 217088,
|
||||
"format-specific": {
|
||||
"type": "qcow2",
|
||||
"data": {
|
||||
"compat": "1.1",
|
||||
"lazy-refcounts": false,
|
||||
"refcount-bits": 16,
|
||||
"corrupt": false
|
||||
}
|
||||
},
|
||||
"full-backing-filename": "/disks/mybacking.qcow2",
|
||||
"backing-filename": "mybacking.qcow2",
|
||||
"dirty-flag": false
|
||||
},
|
||||
{
|
||||
"virtual-size": 25769803776,
|
||||
"filename": "/disks/mybacking.qcow2",
|
||||
"cluster-size": 65536,
|
||||
"format": "qcow2",
|
||||
"actual-size": 393744384,
|
||||
"format-specific": {
|
||||
"type": "qcow2",
|
||||
"data": {
|
||||
"compat": "1.1",
|
||||
"lazy-refcounts": false,
|
||||
"refcount-bits": 16,
|
||||
"corrupt": false
|
||||
}
|
||||
},
|
||||
"dirty-flag": false
|
||||
}]'''
|
||||
|
||||
self.mock_popen.communicate.return_value = [qemu_infos] # pylint: disable=no-member
|
||||
disks = virt.get_disks('test-vm')
|
||||
disk = disks.get('vda')
|
||||
self.assertEqual('/disks/test.qcow2', disk['file'])
|
||||
self.assertEqual('disk', disk['type'])
|
||||
self.assertEqual('/disks/mybacking.qcow2', disk['backing file']['file'])
|
||||
cdrom = disks.get('hda')
|
||||
self.assertEqual('/disks/test-cdrom.iso', cdrom['file'])
|
||||
self.assertEqual('cdrom', cdrom['type'])
|
||||
self.assertFalse('backing file' in cdrom.keys())
|
||||
|
||||
@patch('subprocess.Popen')
|
||||
@patch('subprocess.Popen.communicate', return_value="")
|
||||
@patch('salt.modules.virt.stop', return_value=True)
|
||||
@patch('salt.modules.virt.undefine')
|
||||
@patch('os.remove')
|
||||
def test_purge_default(self, mock_remove, mock_undefine, mock_stop, mock_communicate, mock_popen):
|
||||
def test_purge_default(self, mock_remove, mock_undefine, mock_stop):
|
||||
'''
|
||||
Test virt.purge() with default parameters
|
||||
'''
|
||||
@ -669,17 +967,35 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'''
|
||||
self.set_mock_vm("test-vm", xml)
|
||||
|
||||
qemu_infos = '''[{
|
||||
"virtual-size": 25769803776,
|
||||
"filename": "/disks/test.qcow2",
|
||||
"cluster-size": 65536,
|
||||
"format": "qcow2",
|
||||
"actual-size": 217088,
|
||||
"format-specific": {
|
||||
"type": "qcow2",
|
||||
"data": {
|
||||
"compat": "1.1",
|
||||
"lazy-refcounts": false,
|
||||
"refcount-bits": 16,
|
||||
"corrupt": false
|
||||
}
|
||||
},
|
||||
"dirty-flag": false
|
||||
}]'''
|
||||
|
||||
self.mock_popen.communicate.return_value = [qemu_infos] # pylint: disable=no-member
|
||||
|
||||
res = virt.purge('test-vm')
|
||||
self.assertTrue(res)
|
||||
mock_remove.assert_any_call('/disks/test.qcow2')
|
||||
mock_remove.assert_any_call('/disks/test-cdrom.iso')
|
||||
|
||||
@patch('subprocess.Popen')
|
||||
@patch('subprocess.Popen.communicate', return_value="")
|
||||
@patch('salt.modules.virt.stop', return_value=True)
|
||||
@patch('salt.modules.virt.undefine')
|
||||
@patch('os.remove')
|
||||
def test_purge_noremovable(self, mock_remove, mock_undefine, mock_stop, mock_communicate, mock_popen):
|
||||
def test_purge_noremovable(self, mock_remove, mock_undefine, mock_stop):
|
||||
'''
|
||||
Test virt.purge(removables=False)
|
||||
'''
|
||||
@ -708,6 +1024,26 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'''
|
||||
self.set_mock_vm("test-vm", xml)
|
||||
|
||||
qemu_infos = '''[{
|
||||
"virtual-size": 25769803776,
|
||||
"filename": "/disks/test.qcow2",
|
||||
"cluster-size": 65536,
|
||||
"format": "qcow2",
|
||||
"actual-size": 217088,
|
||||
"format-specific": {
|
||||
"type": "qcow2",
|
||||
"data": {
|
||||
"compat": "1.1",
|
||||
"lazy-refcounts": false,
|
||||
"refcount-bits": 16,
|
||||
"corrupt": false
|
||||
}
|
||||
},
|
||||
"dirty-flag": false
|
||||
}]'''
|
||||
|
||||
self.mock_popen.communicate.return_value = [qemu_infos] # pylint: disable=no-member
|
||||
|
||||
res = virt.purge('test-vm', removables=False)
|
||||
self.assertTrue(res)
|
||||
mock_remove.assert_called_once()
|
||||
@ -1285,6 +1621,23 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
pool_mock.info.return_value = [0, 1234, 5678, 123]
|
||||
pool_mock.autostart.return_value = True
|
||||
pool_mock.isPersistent.return_value = True
|
||||
pool_mock.XMLDesc.return_value = '''<pool type='dir'>
|
||||
<name>default</name>
|
||||
<uuid>d92682d0-33cf-4e10-9837-a216c463e158</uuid>
|
||||
<capacity unit='bytes'>854374301696</capacity>
|
||||
<allocation unit='bytes'>596275986432</allocation>
|
||||
<available unit='bytes'>258098315264</available>
|
||||
<source>
|
||||
</source>
|
||||
<target>
|
||||
<path>/srv/vms</path>
|
||||
<permissions>
|
||||
<mode>0755</mode>
|
||||
<owner>0</owner>
|
||||
<group>0</group>
|
||||
</permissions>
|
||||
</target>
|
||||
</pool>'''
|
||||
self.mock_conn.storagePoolLookupByName.return_value = pool_mock
|
||||
# pylint: enable=no-member
|
||||
|
||||
@ -1296,7 +1649,9 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'allocation': 5678,
|
||||
'free': 123,
|
||||
'autostart': True,
|
||||
'persistent': True}, pool)
|
||||
'persistent': True,
|
||||
'type': 'dir',
|
||||
'target_path': '/srv/vms'}, pool)
|
||||
|
||||
def test_pool_info_notfound(self):
|
||||
'''
|
||||
|
@ -38,7 +38,7 @@ SIMPLE_DICT = {'key1': {'key2': 'val1'}}
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
@skipIf(not consul_pillar.HAS_CONSUL, 'python-consul module not installed')
|
||||
@skipIf(not consul_pillar.consul, 'python-consul module not installed')
|
||||
class ConsulPillarTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'''
|
||||
Test cases for salt.pillar.consul_pillar
|
||||
|
@ -280,6 +280,7 @@ class SSHThinTestCase(TestCase):
|
||||
@patch('salt.utils.thin.ssl_match_hostname', type(str('ssl_match_hostname'), (), {'__file__': '/site-packages/ssl_mh'}))
|
||||
@patch('salt.utils.thin.markupsafe', type(str('markupsafe'), (), {'__file__': '/site-packages/markupsafe'}))
|
||||
@patch('salt.utils.thin.backports_abc', type(str('backports_abc'), (), {'__file__': '/site-packages/backports_abc'}))
|
||||
@patch('salt.utils.thin.concurrent', type(str('concurrent'), (), {'__file__': '/site-packages/concurrent'}))
|
||||
@patch('salt.utils.thin.log', MagicMock())
|
||||
def test_get_tops(self):
|
||||
'''
|
||||
@ -289,7 +290,7 @@ class SSHThinTestCase(TestCase):
|
||||
base_tops = ['/site-packages/salt', '/site-packages/jinja2', '/site-packages/yaml',
|
||||
'/site-packages/tornado', '/site-packages/msgpack', '/site-packages/certifi',
|
||||
'/site-packages/sdp', '/site-packages/sdp_hlp', '/site-packages/ssl_mh',
|
||||
'/site-packages/markupsafe', '/site-packages/backports_abc']
|
||||
'/site-packages/markupsafe', '/site-packages/backports_abc', '/site-packages/concurrent']
|
||||
|
||||
tops = thin.get_tops()
|
||||
assert len(tops) == len(base_tops)
|
||||
@ -306,6 +307,7 @@ class SSHThinTestCase(TestCase):
|
||||
@patch('salt.utils.thin.ssl_match_hostname', type(str('ssl_match_hostname'), (), {'__file__': '/site-packages/ssl_mh'}))
|
||||
@patch('salt.utils.thin.markupsafe', type(str('markupsafe'), (), {'__file__': '/site-packages/markupsafe'}))
|
||||
@patch('salt.utils.thin.backports_abc', type(str('backports_abc'), (), {'__file__': '/site-packages/backports_abc'}))
|
||||
@patch('salt.utils.thin.concurrent', type(str('concurrent'), (), {'__file__': '/site-packages/concurrent'}))
|
||||
@patch('salt.utils.thin.log', MagicMock())
|
||||
def test_get_tops_extra_mods(self):
|
||||
'''
|
||||
@ -314,7 +316,7 @@ class SSHThinTestCase(TestCase):
|
||||
'''
|
||||
base_tops = ['/site-packages/salt', '/site-packages/jinja2', '/site-packages/yaml',
|
||||
'/site-packages/tornado', '/site-packages/msgpack', '/site-packages/certifi',
|
||||
'/site-packages/sdp', '/site-packages/sdp_hlp', '/site-packages/ssl_mh',
|
||||
'/site-packages/sdp', '/site-packages/sdp_hlp', '/site-packages/ssl_mh', '/site-packages/concurrent',
|
||||
'/site-packages/markupsafe', '/site-packages/backports_abc', '/custom/foo', '/custom/bar.py']
|
||||
builtins = sys.version_info.major == 3 and 'builtins' or '__builtin__'
|
||||
with patch('{}.__import__'.format(builtins),
|
||||
@ -335,6 +337,7 @@ class SSHThinTestCase(TestCase):
|
||||
@patch('salt.utils.thin.ssl_match_hostname', type(str('ssl_match_hostname'), (), {'__file__': '/site-packages/ssl_mh'}))
|
||||
@patch('salt.utils.thin.markupsafe', type(str('markupsafe'), (), {'__file__': '/site-packages/markupsafe'}))
|
||||
@patch('salt.utils.thin.backports_abc', type(str('backports_abc'), (), {'__file__': '/site-packages/backports_abc'}))
|
||||
@patch('salt.utils.thin.concurrent', type(str('concurrent'), (), {'__file__': '/site-packages/concurrent'}))
|
||||
@patch('salt.utils.thin.log', MagicMock())
|
||||
def test_get_tops_so_mods(self):
|
||||
'''
|
||||
@ -343,7 +346,7 @@ class SSHThinTestCase(TestCase):
|
||||
'''
|
||||
base_tops = ['/site-packages/salt', '/site-packages/jinja2', '/site-packages/yaml',
|
||||
'/site-packages/tornado', '/site-packages/msgpack', '/site-packages/certifi',
|
||||
'/site-packages/sdp', '/site-packages/sdp_hlp', '/site-packages/ssl_mh',
|
||||
'/site-packages/sdp', '/site-packages/sdp_hlp', '/site-packages/ssl_mh', '/site-packages/concurrent',
|
||||
'/site-packages/markupsafe', '/site-packages/backports_abc', '/custom/foo.so', '/custom/bar.so']
|
||||
builtins = sys.version_info.major == 3 and 'builtins' or '__builtin__'
|
||||
with patch('{}.__import__'.format(builtins),
|
||||
|
@ -105,7 +105,6 @@ class GetHostsTestCase(TestCase):
|
||||
self.mock_si, datacenter_name='fake_datacenter',
|
||||
cluster_name='fake_cluster')
|
||||
mock_get_dc.assert_called_once_with(self.mock_si, 'fake_datacenter')
|
||||
mock_get_cl.assert_called_once_with(mock_dc, 'fake_cluster')
|
||||
mock_get_mors.assert_called_once_with(self.mock_si,
|
||||
vim.HostSystem,
|
||||
container_ref=mock_dc,
|
||||
|
@ -614,7 +614,7 @@ class AssignLicenseTestCase(TestCase):
|
||||
'fake_license_name',
|
||||
entity_name='fake_entity_name')
|
||||
self.mock_update_assigned_license.assert_called_once_with(
|
||||
self.mock_ent_id, self.mock_lic_key)
|
||||
self.mock_ent_id, self.mock_lic_key, 'fake_license_name')
|
||||
|
||||
def test_update_assigned_licenses_call_with_entity(self):
|
||||
salt.utils.vmware.assign_license(self.mock_si,
|
||||
@ -623,7 +623,7 @@ class AssignLicenseTestCase(TestCase):
|
||||
self.mock_entity_ref,
|
||||
'fake_entity_name')
|
||||
self.mock_update_assigned_license.assert_called_once_with(
|
||||
self.mock_moid, self.mock_lic_key)
|
||||
self.mock_moid, self.mock_lic_key, 'fake_license_name')
|
||||
|
||||
def test_update_assigned_licenses_raises_no_permission(self):
|
||||
exc = vim.fault.NoPermission()
|
||||
|
Loading…
Reference in New Issue
Block a user