2020-04-07 14:14:01 +02:00
|
|
|
From e5d42c6313ba051f22f83cbde3da9410fd7fc3b9 Mon Sep 17 00:00:00 2001
|
2020-03-16 16:06:32 +01:00
|
|
|
From: Cedric Bosdonnat <cbosdonnat@suse.com>
|
2020-04-07 14:14:01 +02:00
|
|
|
Date: Fri, 13 Mar 2020 16:38:08 +0100
|
|
|
|
Subject: [PATCH] openSUSE-3000 virt-defined-states (#222)
|
2020-03-16 16:06:32 +01:00
|
|
|
|
|
|
|
* Create virt.pool_defined state out of virt.pool_running
|
|
|
|
|
|
|
|
Users may want to use states to ensure a virtual storage pool is defined
|
|
|
|
and not enforce it to be running. Extract the code that performs the
|
|
|
|
pool definition / update from virt.pool_running state into a
|
|
|
|
virt.pool_defined.
|
|
|
|
|
|
|
|
Obviously the virt.pool_running state calls the virt.pool_defined one.
|
|
|
|
In such a case no additionnal test is needed for virt.pool_defined since
|
|
|
|
this is already tested with virt.pool_running.
|
|
|
|
|
|
|
|
* Add virt.update test parameter
|
|
|
|
|
|
|
|
In order to allow running dry-runs of virt.update module add a test
|
|
|
|
parameter. This will later be used by the virt states.
|
|
|
|
|
|
|
|
* Extract virt.defined state from virt.running
|
|
|
|
|
|
|
|
In order to ensure a virtual guest is defined independently of its
|
|
|
|
status, extract the corresponding code from the virt.running state.
|
|
|
|
|
|
|
|
This commit also handles the __opts__['test'] for the running state.
|
|
|
|
Since the update call only performs changes if needed, deprecate the
|
|
|
|
update parameter.
|
|
|
|
|
|
|
|
* Extract virt.network_defined from virt.network_running
|
|
|
|
|
|
|
|
Just like domains and storage pools, users may want to ensure a network
|
|
|
|
is defined without influencing it's status. Extract the code from
|
|
|
|
network_running state defining the network into a network_defined state.
|
|
|
|
|
|
|
|
While at it, support __opt__['test'] == True in these states. Updating
|
|
|
|
the network definition in the pool_defined state will come in a future
|
|
|
|
PR.
|
|
|
|
|
|
|
|
* Fix virt.update to handle None mem and cpu
|
|
|
|
|
|
|
|
virt.running state now may call virt.update with None mem and cpu
|
|
|
|
parameters. This was not handled in _gen_xml(). Also add some more tests
|
|
|
|
cases matching this for virt.update.
|
|
|
|
---
|
|
|
|
salt/modules/virt.py | 16 +-
|
2020-04-07 14:14:01 +02:00
|
|
|
salt/states/virt.py | 673 +++++++++++++++-----
|
2020-03-16 16:06:32 +01:00
|
|
|
tests/unit/modules/test_virt.py | 26 +
|
|
|
|
tests/unit/states/test_virt.py | 1346 ++++++++++++++++++++++++++++++++-------
|
2020-04-07 14:14:01 +02:00
|
|
|
4 files changed, 1665 insertions(+), 396 deletions(-)
|
2020-03-16 16:06:32 +01:00
|
|
|
|
|
|
|
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
|
2020-04-07 14:14:01 +02:00
|
|
|
index 3889238ecd..f0820e8825 100644
|
2020-03-16 16:06:32 +01:00
|
|
|
--- a/salt/modules/virt.py
|
|
|
|
+++ b/salt/modules/virt.py
|
|
|
|
@@ -1783,6 +1783,7 @@ def update(name,
|
|
|
|
graphics=None,
|
|
|
|
live=True,
|
|
|
|
boot=None,
|
|
|
|
+ test=False,
|
|
|
|
**kwargs):
|
|
|
|
'''
|
|
|
|
Update the definition of an existing domain.
|
|
|
|
@@ -1835,6 +1836,10 @@ def update(name,
|
|
|
|
|
2020-04-07 14:14:01 +02:00
|
|
|
.. versionadded:: 3000
|
2020-03-16 16:06:32 +01:00
|
|
|
|
|
|
|
+ :param test: run in dry-run mode if set to True
|
|
|
|
+
|
|
|
|
+ .. versionadded:: sodium
|
|
|
|
+
|
|
|
|
:return:
|
|
|
|
|
|
|
|
Returns a dictionary indicating the status of what has been done. It is structured in
|
|
|
|
@@ -1880,8 +1885,8 @@ def update(name,
|
|
|
|
boot = _handle_remote_boot_params(boot)
|
|
|
|
|
|
|
|
new_desc = ElementTree.fromstring(_gen_xml(name,
|
|
|
|
- cpu,
|
|
|
|
- mem,
|
|
|
|
+ cpu or 0,
|
|
|
|
+ mem or 0,
|
|
|
|
all_disks,
|
|
|
|
_get_merged_nics(hypervisor, nic_profile, interfaces),
|
|
|
|
hypervisor,
|
|
|
|
@@ -1973,11 +1978,12 @@ def update(name,
|
|
|
|
if changes['disk']:
|
|
|
|
for idx, item in enumerate(changes['disk']['sorted']):
|
|
|
|
source_file = all_disks[idx]['source_file']
|
|
|
|
- if item in changes['disk']['new'] and source_file and not os.path.isfile(source_file):
|
|
|
|
+ if item in changes['disk']['new'] and source_file and not os.path.isfile(source_file) and not test:
|
|
|
|
_qemu_image_create(all_disks[idx])
|
|
|
|
|
|
|
|
try:
|
|
|
|
- conn.defineXML(salt.utils.stringutils.to_str(ElementTree.tostring(desc)))
|
|
|
|
+ if not test:
|
|
|
|
+ conn.defineXML(salt.utils.stringutils.to_str(ElementTree.tostring(desc)))
|
|
|
|
status['definition'] = True
|
|
|
|
except libvirt.libvirtError as err:
|
|
|
|
conn.close()
|
|
|
|
@@ -2010,7 +2016,7 @@ def update(name,
|
|
|
|
|
|
|
|
for cmd in commands:
|
|
|
|
try:
|
|
|
|
- ret = getattr(domain, cmd['cmd'])(*cmd['args'])
|
|
|
|
+ ret = getattr(domain, cmd['cmd'])(*cmd['args']) if not test else 0
|
|
|
|
device_type = cmd['device']
|
|
|
|
if device_type in ['cpu', 'mem']:
|
|
|
|
status[device_type] = not bool(ret)
|
|
|
|
diff --git a/salt/states/virt.py b/salt/states/virt.py
|
2020-04-07 14:14:01 +02:00
|
|
|
index 55a9ad2616..819776d707 100644
|
2020-03-16 16:06:32 +01:00
|
|
|
--- a/salt/states/virt.py
|
|
|
|
+++ b/salt/states/virt.py
|
|
|
|
@@ -14,6 +14,7 @@ for the generation and signing of certificates for systems running libvirt:
|
|
|
|
|
|
|
|
# Import Python libs
|
|
|
|
from __future__ import absolute_import, print_function, unicode_literals
|
|
|
|
+import copy
|
|
|
|
import fnmatch
|
|
|
|
import os
|
|
|
|
|
|
|
|
@@ -245,6 +246,187 @@ def powered_off(name, connection=None, username=None, password=None):
|
|
|
|
connection=connection, username=username, password=password)
|
|
|
|
|
|
|
|
|
|
|
|
+def defined(name,
|
|
|
|
+ cpu=None,
|
|
|
|
+ mem=None,
|
|
|
|
+ vm_type=None,
|
|
|
|
+ disk_profile=None,
|
|
|
|
+ disks=None,
|
|
|
|
+ nic_profile=None,
|
|
|
|
+ interfaces=None,
|
|
|
|
+ graphics=None,
|
|
|
|
+ seed=True,
|
|
|
|
+ install=True,
|
|
|
|
+ pub_key=None,
|
|
|
|
+ priv_key=None,
|
|
|
|
+ connection=None,
|
|
|
|
+ username=None,
|
|
|
|
+ password=None,
|
|
|
|
+ os_type=None,
|
|
|
|
+ arch=None,
|
|
|
|
+ boot=None,
|
|
|
|
+ update=True):
|
|
|
|
+ '''
|
|
|
|
+ Starts an existing guest, or defines and starts a new VM with specified arguments.
|
|
|
|
+
|
|
|
|
+ .. versionadded:: sodium
|
|
|
|
+
|
|
|
|
+ :param name: name of the virtual machine to run
|
|
|
|
+ :param cpu: number of CPUs for the virtual machine to create
|
|
|
|
+ :param mem: amount of memory in MiB for the new virtual machine
|
|
|
|
+ :param vm_type: force virtual machine type for the new VM. The default value is taken from
|
|
|
|
+ the host capabilities. This could be useful for example to use ``'qemu'`` type instead
|
|
|
|
+ of the ``'kvm'`` one.
|
|
|
|
+ :param disk_profile:
|
|
|
|
+ Name of the disk profile to use for the new virtual machine
|
|
|
|
+ :param disks:
|
|
|
|
+ List of disk to create for the new virtual machine.
|
|
|
|
+ See :ref:`init-disk-def` for more details on the items on this list.
|
|
|
|
+ :param nic_profile:
|
|
|
|
+ Name of the network interfaces profile to use for the new virtual machine
|
|
|
|
+ :param interfaces:
|
|
|
|
+ List of network interfaces to create for the new virtual machine.
|
|
|
|
+ See :ref:`init-nic-def` for more details on the items on this list.
|
|
|
|
+ :param graphics:
|
|
|
|
+ Graphics device to create for the new virtual machine.
|
|
|
|
+ See :ref:`init-graphics-def` for more details on this dictionary
|
|
|
|
+ :param saltenv:
|
|
|
|
+ Fileserver environment (Default: ``'base'``).
|
|
|
|
+ See :mod:`cp module for more details <salt.modules.cp>`
|
|
|
|
+ :param seed: ``True`` to seed the disk image. Only used when the ``image`` parameter is provided.
|
|
|
|
+ (Default: ``True``)
|
|
|
|
+ :param install: install salt minion if absent (Default: ``True``)
|
|
|
|
+ :param pub_key: public key to seed with (Default: ``None``)
|
|
|
|
+ :param priv_key: public key to seed with (Default: ``None``)
|
|
|
|
+ :param seed_cmd: Salt command to execute to seed the image. (Default: ``'seed.apply'``)
|
|
|
|
+ :param connection: libvirt connection URI, overriding defaults
|
|
|
|
+ :param username: username to connect with, overriding defaults
|
|
|
|
+ :param password: password to connect with, overriding defaults
|
|
|
|
+ :param os_type:
|
|
|
|
+ type of virtualization as found in the ``//os/type`` element of the libvirt definition.
|
|
|
|
+ The default value is taken from the host capabilities, with a preference for ``hvm``.
|
|
|
|
+ Only used when creating a new virtual machine.
|
|
|
|
+ :param arch:
|
|
|
|
+ architecture of the virtual machine. The default value is taken from the host capabilities,
|
|
|
|
+ but ``x86_64`` is prefed over ``i686``. Only used when creating a new virtual machine.
|
|
|
|
+
|
|
|
|
+ :param boot:
|
|
|
|
+ Specifies kernel for the virtual machine, as well as boot parameters
|
|
|
|
+ for the virtual machine. This is an optionl parameter, and all of the
|
|
|
|
+ keys are optional within the dictionary. If a remote path is provided
|
|
|
|
+ to kernel or initrd, salt will handle the downloading of the specified
|
|
|
|
+ remote fild, and will modify the XML accordingly.
|
|
|
|
+
|
|
|
|
+ .. code-block:: python
|
|
|
|
+
|
|
|
|
+ {
|
|
|
|
+ 'kernel': '/root/f8-i386-vmlinuz',
|
|
|
|
+ 'initrd': '/root/f8-i386-initrd',
|
|
|
|
+ 'cmdline': 'console=ttyS0 ks=http://example.com/f8-i386/os/'
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ :param update: set to ``False`` to prevent updating a defined domain. (Default: ``True``)
|
|
|
|
+
|
|
|
|
+ .. deprecated:: sodium
|
|
|
|
+
|
|
|
|
+ .. rubric:: Example States
|
|
|
|
+
|
|
|
|
+ Make sure a virtual machine called ``domain_name`` is defined:
|
|
|
|
+
|
|
|
|
+ .. code-block:: yaml
|
|
|
|
+
|
|
|
|
+ domain_name:
|
|
|
|
+ virt.defined:
|
|
|
|
+ - cpu: 2
|
|
|
|
+ - mem: 2048
|
|
|
|
+ - disk_profile: prod
|
|
|
|
+ - disks:
|
|
|
|
+ - name: system
|
|
|
|
+ size: 8192
|
|
|
|
+ overlay_image: True
|
|
|
|
+ pool: default
|
|
|
|
+ image: /path/to/image.qcow2
|
|
|
|
+ - name: data
|
|
|
|
+ size: 16834
|
|
|
|
+ - nic_profile: prod
|
|
|
|
+ - interfaces:
|
|
|
|
+ - name: eth0
|
|
|
|
+ mac: 01:23:45:67:89:AB
|
|
|
|
+ - name: eth1
|
|
|
|
+ type: network
|
|
|
|
+ source: admin
|
|
|
|
+ - graphics:
|
|
|
|
+ type: spice
|
|
|
|
+ listen:
|
|
|
|
+ type: address
|
|
|
|
+ address: 192.168.0.125
|
|
|
|
+
|
|
|
|
+ '''
|
|
|
|
+
|
|
|
|
+ ret = {'name': name,
|
|
|
|
+ 'changes': {},
|
|
|
|
+ 'result': True if not __opts__['test'] else None,
|
|
|
|
+ 'comment': ''
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ try:
|
|
|
|
+ if name in __salt__['virt.list_domains'](connection=connection, username=username, password=password):
|
|
|
|
+ status = {}
|
|
|
|
+ if update:
|
|
|
|
+ status = __salt__['virt.update'](name,
|
|
|
|
+ cpu=cpu,
|
|
|
|
+ mem=mem,
|
|
|
|
+ disk_profile=disk_profile,
|
|
|
|
+ disks=disks,
|
|
|
|
+ nic_profile=nic_profile,
|
|
|
|
+ interfaces=interfaces,
|
|
|
|
+ graphics=graphics,
|
|
|
|
+ live=True,
|
|
|
|
+ connection=connection,
|
|
|
|
+ username=username,
|
|
|
|
+ password=password,
|
|
|
|
+ boot=boot,
|
|
|
|
+ test=__opts__['test'])
|
|
|
|
+ ret['changes'][name] = status
|
|
|
|
+ if not status.get('definition'):
|
|
|
|
+ ret['comment'] = 'Domain {0} unchanged'.format(name)
|
|
|
|
+ ret['result'] = True
|
|
|
|
+ elif status.get('errors'):
|
|
|
|
+ ret['comment'] = 'Domain {0} updated with live update(s) failures'.format(name)
|
|
|
|
+ else:
|
|
|
|
+ ret['comment'] = 'Domain {0} updated'.format(name)
|
|
|
|
+ else:
|
|
|
|
+ if not __opts__['test']:
|
|
|
|
+ __salt__['virt.init'](name,
|
|
|
|
+ cpu=cpu,
|
|
|
|
+ mem=mem,
|
|
|
|
+ os_type=os_type,
|
|
|
|
+ arch=arch,
|
|
|
|
+ hypervisor=vm_type,
|
|
|
|
+ disk=disk_profile,
|
|
|
|
+ disks=disks,
|
|
|
|
+ nic=nic_profile,
|
|
|
|
+ interfaces=interfaces,
|
|
|
|
+ graphics=graphics,
|
|
|
|
+ seed=seed,
|
|
|
|
+ install=install,
|
|
|
|
+ pub_key=pub_key,
|
|
|
|
+ priv_key=priv_key,
|
|
|
|
+ connection=connection,
|
|
|
|
+ username=username,
|
|
|
|
+ password=password,
|
|
|
|
+ boot=boot,
|
|
|
|
+ start=False)
|
|
|
|
+ ret['changes'][name] = {'definition': True}
|
|
|
|
+ ret['comment'] = 'Domain {0} defined'.format(name)
|
|
|
|
+ except libvirt.libvirtError as err:
|
|
|
|
+ # Something bad happened when defining / updating the VM, report it
|
|
|
|
+ ret['comment'] = six.text_type(err)
|
|
|
|
+ ret['result'] = False
|
|
|
|
+
|
|
|
|
+ return ret
|
|
|
|
+
|
|
|
|
+
|
|
|
|
def running(name,
|
|
|
|
cpu=None,
|
|
|
|
mem=None,
|
|
|
|
@@ -326,9 +508,10 @@ def running(name,
|
|
|
|
:param seed_cmd: Salt command to execute to seed the image. (Default: ``'seed.apply'``)
|
|
|
|
|
|
|
|
.. versionadded:: 2019.2.0
|
|
|
|
- :param update: set to ``True`` to update a defined module. (Default: ``False``)
|
|
|
|
+ :param update: set to ``True`` to update a defined domain. (Default: ``False``)
|
|
|
|
|
|
|
|
.. versionadded:: 2019.2.0
|
|
|
|
+ .. deprecated:: sodium
|
|
|
|
:param connection: libvirt connection URI, overriding defaults
|
|
|
|
|
|
|
|
.. versionadded:: 2019.2.0
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -424,93 +607,74 @@ def running(name,
|
2020-03-16 16:06:32 +01:00
|
|
|
address: 192.168.0.125
|
|
|
|
|
|
|
|
'''
|
|
|
|
-
|
|
|
|
- ret = {'name': name,
|
|
|
|
- 'changes': {},
|
|
|
|
- 'result': True,
|
|
|
|
- 'comment': '{0} is running'.format(name)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- try:
|
|
|
|
+ merged_disks = disks
|
|
|
|
+ if image:
|
|
|
|
+ default_disks = [{'system': {}}]
|
|
|
|
+ disknames = ['system']
|
|
|
|
+ if disk_profile:
|
|
|
|
+ disklist = copy.deepcopy(
|
|
|
|
+ __salt__['config.get']('virt:disk', {}).get(disk_profile, default_disks))
|
|
|
|
+ disknames = disklist.keys()
|
|
|
|
+ disk = {'name': disknames[0], 'image': image}
|
|
|
|
+ if merged_disks:
|
|
|
|
+ first_disk = [d for d in merged_disks if d.get('name') == disknames[0]]
|
|
|
|
+ if first_disk and 'image' not in first_disk[0]:
|
|
|
|
+ first_disk[0]['image'] = image
|
|
|
|
+ else:
|
|
|
|
+ merged_disks.append(disk)
|
|
|
|
+ else:
|
|
|
|
+ merged_disks = [disk]
|
|
|
|
+ salt.utils.versions.warn_until(
|
|
|
|
+ 'Sodium',
|
|
|
|
+ '\'image\' parameter has been deprecated. Rather use the \'disks\' parameter '
|
|
|
|
+ 'to override or define the image. \'image\' will be removed in {version}.'
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ if not update:
|
|
|
|
+ salt.utils.versions.warn_until('Magnesium',
|
|
|
|
+ '\'update\' parameter has been deprecated. Future behavior will be the one of update=True'
|
|
|
|
+ 'It will be removed in {version}.')
|
|
|
|
+ ret = defined(name,
|
|
|
|
+ cpu=cpu,
|
|
|
|
+ mem=mem,
|
|
|
|
+ vm_type=vm_type,
|
|
|
|
+ disk_profile=disk_profile,
|
|
|
|
+ disks=merged_disks,
|
|
|
|
+ nic_profile=nic_profile,
|
|
|
|
+ interfaces=interfaces,
|
|
|
|
+ graphics=graphics,
|
|
|
|
+ seed=seed,
|
|
|
|
+ install=install,
|
|
|
|
+ pub_key=pub_key,
|
|
|
|
+ priv_key=priv_key,
|
|
|
|
+ os_type=os_type,
|
|
|
|
+ arch=arch,
|
|
|
|
+ boot=boot,
|
|
|
|
+ update=update,
|
|
|
|
+ connection=connection,
|
|
|
|
+ username=username,
|
|
|
|
+ password=password)
|
|
|
|
+
|
|
|
|
+ result = True if not __opts__['test'] else None
|
|
|
|
+ if ret['result'] is None or ret['result']:
|
|
|
|
+ changed = ret['changes'][name].get('definition', False)
|
|
|
|
try:
|
|
|
|
domain_state = __salt__['virt.vm_state'](name)
|
2020-04-07 14:14:01 +02:00
|
|
|
if domain_state.get(name) != 'running':
|
2020-03-16 16:06:32 +01:00
|
|
|
- action_msg = 'started'
|
|
|
|
- if update:
|
|
|
|
- status = __salt__['virt.update'](name,
|
|
|
|
- cpu=cpu,
|
|
|
|
- mem=mem,
|
|
|
|
- disk_profile=disk_profile,
|
|
|
|
- disks=disks,
|
|
|
|
- nic_profile=nic_profile,
|
|
|
|
- interfaces=interfaces,
|
|
|
|
- graphics=graphics,
|
|
|
|
- live=False,
|
|
|
|
- connection=connection,
|
|
|
|
- username=username,
|
|
|
|
- password=password,
|
|
|
|
- boot=boot)
|
|
|
|
- if status['definition']:
|
|
|
|
- action_msg = 'updated and started'
|
|
|
|
- __salt__['virt.start'](name)
|
|
|
|
- ret['changes'][name] = 'Domain {0}'.format(action_msg)
|
|
|
|
- ret['comment'] = 'Domain {0} {1}'.format(name, action_msg)
|
|
|
|
- else:
|
|
|
|
- if update:
|
|
|
|
- status = __salt__['virt.update'](name,
|
|
|
|
- cpu=cpu,
|
|
|
|
- mem=mem,
|
|
|
|
- disk_profile=disk_profile,
|
|
|
|
- disks=disks,
|
|
|
|
- nic_profile=nic_profile,
|
|
|
|
- interfaces=interfaces,
|
|
|
|
- graphics=graphics,
|
|
|
|
- connection=connection,
|
|
|
|
- username=username,
|
|
|
|
- password=password,
|
|
|
|
- boot=boot)
|
|
|
|
- ret['changes'][name] = status
|
|
|
|
- if status.get('errors', None):
|
|
|
|
- ret['comment'] = 'Domain {0} updated, but some live update(s) failed'.format(name)
|
|
|
|
- elif not status['definition']:
|
|
|
|
- ret['comment'] = 'Domain {0} exists and is running'.format(name)
|
|
|
|
- else:
|
|
|
|
- ret['comment'] = 'Domain {0} updated, restart to fully apply the changes'.format(name)
|
|
|
|
- else:
|
|
|
|
- ret['comment'] = 'Domain {0} exists and is running'.format(name)
|
|
|
|
- except CommandExecutionError:
|
|
|
|
- if image:
|
|
|
|
- salt.utils.versions.warn_until(
|
|
|
|
- 'Sodium',
|
|
|
|
- '\'image\' parameter has been deprecated. Rather use the \'disks\' parameter '
|
|
|
|
- 'to override or define the image. \'image\' will be removed in {version}.'
|
|
|
|
- )
|
|
|
|
- __salt__['virt.init'](name,
|
|
|
|
- cpu=cpu,
|
|
|
|
- mem=mem,
|
|
|
|
- os_type=os_type,
|
|
|
|
- arch=arch,
|
|
|
|
- image=image,
|
|
|
|
- hypervisor=vm_type,
|
|
|
|
- disk=disk_profile,
|
|
|
|
- disks=disks,
|
|
|
|
- nic=nic_profile,
|
|
|
|
- interfaces=interfaces,
|
|
|
|
- graphics=graphics,
|
|
|
|
- seed=seed,
|
|
|
|
- install=install,
|
|
|
|
- pub_key=pub_key,
|
|
|
|
- priv_key=priv_key,
|
|
|
|
- connection=connection,
|
|
|
|
- username=username,
|
|
|
|
- password=password,
|
|
|
|
- boot=boot)
|
|
|
|
- ret['changes'][name] = 'Domain defined and started'
|
|
|
|
- ret['comment'] = 'Domain {0} defined and started'.format(name)
|
|
|
|
- except libvirt.libvirtError as err:
|
|
|
|
- # Something bad happened when starting / updating the VM, report it
|
|
|
|
- ret['comment'] = six.text_type(err)
|
|
|
|
- ret['result'] = False
|
|
|
|
+ if not __opts__['test']:
|
|
|
|
+ __salt__['virt.start'](name, connection=connection, username=username, password=password)
|
|
|
|
+ comment = 'Domain {} started'.format(name)
|
|
|
|
+ if not ret['comment'].endswith('unchanged'):
|
|
|
|
+ comment = '{} and started'.format(ret['comment'])
|
|
|
|
+ ret['comment'] = comment
|
|
|
|
+ ret['changes'][name]['started'] = True
|
|
|
|
+ elif not changed:
|
|
|
|
+ ret['comment'] = 'Domain {0} exists and is running'.format(name)
|
|
|
|
+
|
|
|
|
+ except libvirt.libvirtError as err:
|
|
|
|
+ # Something bad happened when starting / updating the VM, report it
|
|
|
|
+ ret['comment'] = six.text_type(err)
|
|
|
|
+ ret['result'] = False
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -670,6 +834,106 @@ def reverted(name, snapshot=None, cleanup=False): # pylint: disable=redefined-o
|
2020-03-16 16:06:32 +01:00
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
|
|
+def network_defined(name,
|
|
|
|
+ bridge,
|
|
|
|
+ forward,
|
|
|
|
+ vport=None,
|
|
|
|
+ tag=None,
|
|
|
|
+ ipv4_config=None,
|
|
|
|
+ ipv6_config=None,
|
|
|
|
+ autostart=True,
|
|
|
|
+ connection=None,
|
|
|
|
+ username=None,
|
|
|
|
+ password=None):
|
|
|
|
+ '''
|
|
|
|
+ Defines a new network with specified arguments.
|
|
|
|
+
|
|
|
|
+ :param bridge: Bridge name
|
|
|
|
+ :param forward: Forward mode(bridge, router, nat)
|
|
|
|
+ :param vport: Virtualport type (Default: ``'None'``)
|
|
|
|
+ :param tag: Vlan tag (Default: ``'None'``)
|
|
|
|
+ :param ipv4_config:
|
|
|
|
+ IPv4 network configuration. See the :py:func`virt.network_define
|
|
|
|
+ <salt.modules.virt.network_define>` function corresponding parameter documentation
|
|
|
|
+ for more details on this dictionary.
|
|
|
|
+ (Default: None).
|
|
|
|
+ :param ipv6_config:
|
|
|
|
+ IPv6 network configuration. See the :py:func`virt.network_define
|
|
|
|
+ <salt.modules.virt.network_define>` function corresponding parameter documentation
|
|
|
|
+ for more details on this dictionary.
|
|
|
|
+ (Default: None).
|
|
|
|
+ :param autostart: Network autostart (default ``'True'``)
|
|
|
|
+ :param connection: libvirt connection URI, overriding defaults
|
|
|
|
+ :param username: username to connect with, overriding defaults
|
|
|
|
+ :param password: password to connect with, overriding defaults
|
|
|
|
+
|
|
|
|
+ .. versionadded:: sodium
|
|
|
|
+
|
|
|
|
+ .. code-block:: yaml
|
|
|
|
+
|
|
|
|
+ network_name:
|
|
|
|
+ virt.network_defined
|
|
|
|
+
|
|
|
|
+ .. code-block:: yaml
|
|
|
|
+
|
|
|
|
+ network_name:
|
|
|
|
+ virt.network_defined:
|
|
|
|
+ - bridge: main
|
|
|
|
+ - forward: bridge
|
|
|
|
+ - vport: openvswitch
|
|
|
|
+ - tag: 180
|
|
|
|
+ - autostart: True
|
|
|
|
+
|
|
|
|
+ .. code-block:: yaml
|
|
|
|
+
|
|
|
|
+ network_name:
|
|
|
|
+ virt.network_defined:
|
|
|
|
+ - bridge: natted
|
|
|
|
+ - forward: nat
|
|
|
|
+ - ipv4_config:
|
|
|
|
+ cidr: 192.168.42.0/24
|
|
|
|
+ dhcp_ranges:
|
|
|
|
+ - start: 192.168.42.10
|
|
|
|
+ end: 192.168.42.25
|
|
|
|
+ - start: 192.168.42.100
|
|
|
|
+ end: 192.168.42.150
|
|
|
|
+ - autostart: True
|
|
|
|
+
|
|
|
|
+ '''
|
|
|
|
+ ret = {'name': name,
|
|
|
|
+ 'changes': {},
|
|
|
|
+ 'result': True if not __opts__['test'] else None,
|
|
|
|
+ 'comment': ''
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ try:
|
|
|
|
+ info = __salt__['virt.network_info'](name, connection=connection, username=username, password=password)
|
|
|
|
+ if info and info[name]:
|
|
|
|
+ ret['comment'] = 'Network {0} exists'.format(name)
|
|
|
|
+ ret['result'] = True
|
|
|
|
+ else:
|
|
|
|
+ if not __opts__['test']:
|
|
|
|
+ __salt__['virt.network_define'](name,
|
|
|
|
+ bridge,
|
|
|
|
+ forward,
|
|
|
|
+ vport=vport,
|
|
|
|
+ tag=tag,
|
|
|
|
+ ipv4_config=ipv4_config,
|
|
|
|
+ ipv6_config=ipv6_config,
|
|
|
|
+ autostart=autostart,
|
|
|
|
+ start=False,
|
|
|
|
+ connection=connection,
|
|
|
|
+ username=username,
|
|
|
|
+ password=password)
|
|
|
|
+ ret['changes'][name] = 'Network defined'
|
|
|
|
+ ret['comment'] = 'Network {0} defined'.format(name)
|
|
|
|
+ except libvirt.libvirtError as err:
|
|
|
|
+ ret['result'] = False
|
|
|
|
+ ret['comment'] = err.get_error_message()
|
|
|
|
+
|
|
|
|
+ return ret
|
|
|
|
+
|
|
|
|
+
|
|
|
|
def network_running(name,
|
|
|
|
bridge,
|
|
|
|
forward,
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -715,13 +979,13 @@ def network_running(name,
|
2020-03-16 16:06:32 +01:00
|
|
|
|
|
|
|
.. code-block:: yaml
|
|
|
|
|
|
|
|
- domain_name:
|
|
|
|
- virt.network_define
|
|
|
|
+ network_name:
|
|
|
|
+ virt.network_running
|
|
|
|
|
|
|
|
.. code-block:: yaml
|
|
|
|
|
|
|
|
network_name:
|
|
|
|
- virt.network_define:
|
|
|
|
+ virt.network_running:
|
|
|
|
- bridge: main
|
|
|
|
- forward: bridge
|
|
|
|
- vport: openvswitch
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -731,7 +995,7 @@ def network_running(name,
|
2020-03-16 16:06:32 +01:00
|
|
|
.. code-block:: yaml
|
|
|
|
|
|
|
|
network_name:
|
|
|
|
- virt.network_define:
|
|
|
|
+ virt.network_running:
|
|
|
|
- bridge: natted
|
|
|
|
- forward: nat
|
|
|
|
- ipv4_config:
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -744,44 +1008,46 @@ def network_running(name,
|
2020-03-16 16:06:32 +01:00
|
|
|
- autostart: True
|
|
|
|
|
|
|
|
'''
|
|
|
|
- ret = {'name': name,
|
|
|
|
- 'changes': {},
|
|
|
|
- 'result': True,
|
|
|
|
- 'comment': ''
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- try:
|
|
|
|
- info = __salt__['virt.network_info'](name, connection=connection, username=username, password=password)
|
|
|
|
- if info:
|
|
|
|
- if info[name]['active']:
|
|
|
|
- ret['comment'] = 'Network {0} exists and is running'.format(name)
|
|
|
|
+ ret = network_defined(name,
|
|
|
|
+ bridge,
|
|
|
|
+ forward,
|
|
|
|
+ vport=vport,
|
|
|
|
+ tag=tag,
|
|
|
|
+ ipv4_config=ipv4_config,
|
|
|
|
+ ipv6_config=ipv6_config,
|
|
|
|
+ autostart=autostart,
|
|
|
|
+ connection=connection,
|
|
|
|
+ username=username,
|
|
|
|
+ password=password)
|
|
|
|
+
|
|
|
|
+ defined = name in ret['changes'] and ret['changes'][name].startswith('Network defined')
|
|
|
|
+
|
|
|
|
+ result = True if not __opts__['test'] else None
|
|
|
|
+ if ret['result'] is None or ret['result']:
|
|
|
|
+ try:
|
|
|
|
+ info = __salt__['virt.network_info'](name, connection=connection, username=username, password=password)
|
|
|
|
+ # In the corner case where test=True and the network wasn't defined
|
|
|
|
+ # we may not get the network in the info dict and that is normal.
|
|
|
|
+ if info.get(name, {}).get('active', False):
|
|
|
|
+ ret['comment'] = '{} and is running'.format(ret['comment'])
|
|
|
|
else:
|
|
|
|
- __salt__['virt.network_start'](name, connection=connection, username=username, password=password)
|
|
|
|
- ret['changes'][name] = 'Network started'
|
|
|
|
- ret['comment'] = 'Network {0} started'.format(name)
|
|
|
|
- else:
|
|
|
|
- __salt__['virt.network_define'](name,
|
|
|
|
- bridge,
|
|
|
|
- forward,
|
|
|
|
- vport=vport,
|
|
|
|
- tag=tag,
|
|
|
|
- ipv4_config=ipv4_config,
|
|
|
|
- ipv6_config=ipv6_config,
|
|
|
|
- autostart=autostart,
|
|
|
|
- start=True,
|
|
|
|
- connection=connection,
|
|
|
|
- username=username,
|
|
|
|
- password=password)
|
|
|
|
- ret['changes'][name] = 'Network defined and started'
|
|
|
|
- ret['comment'] = 'Network {0} defined and started'.format(name)
|
|
|
|
- except libvirt.libvirtError as err:
|
|
|
|
- ret['result'] = False
|
|
|
|
- ret['comment'] = err.get_error_message()
|
|
|
|
+ if not __opts__['test']:
|
|
|
|
+ __salt__['virt.network_start'](name, connection=connection, username=username, password=password)
|
|
|
|
+ change = 'Network started'
|
|
|
|
+ if name in ret['changes']:
|
|
|
|
+ change = '{} and started'.format(ret['changes'][name])
|
|
|
|
+ ret['changes'][name] = change
|
|
|
|
+ ret['comment'] = '{} and started'.format(ret['comment'])
|
|
|
|
+ ret['result'] = result
|
|
|
|
+
|
|
|
|
+ except libvirt.libvirtError as err:
|
|
|
|
+ ret['result'] = False
|
|
|
|
+ ret['comment'] = err.get_error_message()
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
|
|
-def pool_running(name,
|
|
|
|
+def pool_defined(name,
|
|
|
|
ptype=None,
|
|
|
|
target=None,
|
|
|
|
permissions=None,
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -792,9 +1058,9 @@ def pool_running(name,
|
2020-03-16 16:06:32 +01:00
|
|
|
username=None,
|
|
|
|
password=None):
|
|
|
|
'''
|
|
|
|
- Defines and starts a new pool with specified arguments.
|
|
|
|
+ Defines a new pool with specified arguments.
|
|
|
|
|
|
|
|
- .. versionadded:: 2019.2.0
|
|
|
|
+ .. versionadded:: sodium
|
|
|
|
|
|
|
|
:param ptype: libvirt pool type
|
|
|
|
:param target: full path to the target device or folder. (Default: ``None``)
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -816,12 +1082,7 @@ def pool_running(name,
|
2020-03-16 16:06:32 +01:00
|
|
|
.. code-block:: yaml
|
|
|
|
|
|
|
|
pool_name:
|
|
|
|
- virt.pool_define
|
|
|
|
-
|
|
|
|
- .. code-block:: yaml
|
|
|
|
-
|
|
|
|
- pool_name:
|
|
|
|
- virt.pool_define:
|
|
|
|
+ virt.pool_defined:
|
|
|
|
- ptype: netfs
|
|
|
|
- target: /mnt/cifs
|
|
|
|
- permissions:
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -884,29 +1145,19 @@ def pool_running(name,
|
2020-03-16 16:06:32 +01:00
|
|
|
username=username,
|
|
|
|
password=password)
|
|
|
|
|
|
|
|
- action = "started"
|
|
|
|
- if info[name]['state'] == 'running':
|
|
|
|
- action = "restarted"
|
|
|
|
+ action = ''
|
|
|
|
+ if info[name]['state'] != 'running':
|
|
|
|
if not __opts__['test']:
|
|
|
|
- __salt__['virt.pool_stop'](name, connection=connection, username=username, password=password)
|
|
|
|
-
|
|
|
|
- if not __opts__['test']:
|
|
|
|
- __salt__['virt.pool_build'](name, connection=connection, username=username, password=password)
|
|
|
|
- __salt__['virt.pool_start'](name, connection=connection, username=username, password=password)
|
|
|
|
+ __salt__['virt.pool_build'](name, connection=connection, username=username, password=password)
|
|
|
|
+ action = ', built'
|
|
|
|
|
|
|
|
- autostart_str = ', autostart flag changed' if needs_autostart else ''
|
|
|
|
- ret['changes'][name] = 'Pool updated, built{0} and {1}'.format(autostart_str, action)
|
|
|
|
- ret['comment'] = 'Pool {0} updated, built{1} and {2}'.format(name, autostart_str, action)
|
|
|
|
+ action = '{}, autostart flag changed'.format(action) if needs_autostart else action
|
|
|
|
+ ret['changes'][name] = 'Pool updated{0}'.format(action)
|
|
|
|
+ ret['comment'] = 'Pool {0} updated{1}'.format(name, action)
|
|
|
|
|
|
|
|
else:
|
|
|
|
- if info[name]['state'] == 'running':
|
|
|
|
- ret['comment'] = 'Pool {0} unchanged and is running'.format(name)
|
|
|
|
- ret['result'] = True
|
|
|
|
- else:
|
|
|
|
- ret['changes'][name] = 'Pool started'
|
|
|
|
- ret['comment'] = 'Pool {0} started'.format(name)
|
|
|
|
- if not __opts__['test']:
|
|
|
|
- __salt__['virt.pool_start'](name, connection=connection, username=username, password=password)
|
|
|
|
+ ret['comment'] = 'Pool {0} unchanged'.format(name)
|
|
|
|
+ ret['result'] = True
|
|
|
|
else:
|
|
|
|
needs_autostart = autostart
|
|
|
|
if not __opts__['test']:
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -932,17 +1183,12 @@ def pool_running(name,
|
2020-03-16 16:06:32 +01:00
|
|
|
connection=connection,
|
|
|
|
username=username,
|
|
|
|
password=password)
|
|
|
|
-
|
|
|
|
- __salt__['virt.pool_start'](name,
|
|
|
|
- connection=connection,
|
|
|
|
- username=username,
|
|
|
|
- password=password)
|
|
|
|
if needs_autostart:
|
|
|
|
- ret['changes'][name] = 'Pool defined, started and marked for autostart'
|
|
|
|
- ret['comment'] = 'Pool {0} defined, started and marked for autostart'.format(name)
|
|
|
|
+ ret['changes'][name] = 'Pool defined, marked for autostart'
|
|
|
|
+ ret['comment'] = 'Pool {0} defined, marked for autostart'.format(name)
|
|
|
|
else:
|
|
|
|
- ret['changes'][name] = 'Pool defined and started'
|
|
|
|
- ret['comment'] = 'Pool {0} defined and started'.format(name)
|
|
|
|
+ ret['changes'][name] = 'Pool defined'
|
|
|
|
+ ret['comment'] = 'Pool {0} defined'.format(name)
|
|
|
|
|
|
|
|
if needs_autostart:
|
|
|
|
if not __opts__['test']:
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -958,6 +1204,117 @@ def pool_running(name,
|
2020-03-16 16:06:32 +01:00
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
|
|
+def pool_running(name,
|
|
|
|
+ ptype=None,
|
|
|
|
+ target=None,
|
|
|
|
+ permissions=None,
|
|
|
|
+ source=None,
|
|
|
|
+ transient=False,
|
|
|
|
+ autostart=True,
|
|
|
|
+ connection=None,
|
|
|
|
+ username=None,
|
|
|
|
+ password=None):
|
|
|
|
+ '''
|
|
|
|
+ Defines and starts a new pool with specified arguments.
|
|
|
|
+
|
|
|
|
+ .. versionadded:: 2019.2.0
|
|
|
|
+
|
|
|
|
+ :param ptype: libvirt pool type
|
|
|
|
+ :param target: full path to the target device or folder. (Default: ``None``)
|
|
|
|
+ :param permissions:
|
|
|
|
+ target permissions. See :ref:`pool-define-permissions` for more details on this structure.
|
|
|
|
+ :param source:
|
|
|
|
+ dictionary containing keys matching the ``source_*`` parameters in function
|
|
|
|
+ :func:`salt.modules.virt.pool_define`.
|
|
|
|
+ :param transient:
|
|
|
|
+ when set to ``True``, the pool will be automatically undefined after being stopped. (Default: ``False``)
|
|
|
|
+ :param autostart:
|
|
|
|
+ Whether to start the pool when booting the host. (Default: ``True``)
|
|
|
|
+ :param start:
|
|
|
|
+ When ``True``, define and start the pool, otherwise the pool will be left stopped.
|
|
|
|
+ :param connection: libvirt connection URI, overriding defaults
|
|
|
|
+ :param username: username to connect with, overriding defaults
|
|
|
|
+ :param password: password to connect with, overriding defaults
|
|
|
|
+
|
|
|
|
+ .. code-block:: yaml
|
|
|
|
+
|
|
|
|
+ pool_name:
|
|
|
|
+ virt.pool_running
|
|
|
|
+
|
|
|
|
+ .. code-block:: yaml
|
|
|
|
+
|
|
|
|
+ pool_name:
|
|
|
|
+ virt.pool_running:
|
|
|
|
+ - ptype: netfs
|
|
|
|
+ - target: /mnt/cifs
|
|
|
|
+ - permissions:
|
|
|
|
+ - mode: 0770
|
|
|
|
+ - owner: 1000
|
|
|
|
+ - group: 100
|
|
|
|
+ - source:
|
|
|
|
+ dir: samba_share
|
|
|
|
+ hosts:
|
|
|
|
+ - one.example.com
|
|
|
|
+ - two.example.com
|
|
|
|
+ format: cifs
|
|
|
|
+ - autostart: True
|
|
|
|
+
|
|
|
|
+ '''
|
|
|
|
+ ret = pool_defined(name,
|
|
|
|
+ ptype=ptype,
|
|
|
|
+ target=target,
|
|
|
|
+ permissions=permissions,
|
|
|
|
+ source=source,
|
|
|
|
+ transient=transient,
|
|
|
|
+ autostart=autostart,
|
|
|
|
+ connection=connection,
|
|
|
|
+ username=username,
|
|
|
|
+ password=password)
|
|
|
|
+ defined = name in ret['changes'] and ret['changes'][name].startswith('Pool defined')
|
|
|
|
+ updated = name in ret['changes'] and ret['changes'][name].startswith('Pool updated')
|
|
|
|
+
|
|
|
|
+ result = True if not __opts__['test'] else None
|
|
|
|
+ if ret['result'] is None or ret['result']:
|
|
|
|
+ try:
|
|
|
|
+ info = __salt__['virt.pool_info'](name, connection=connection, username=username, password=password)
|
|
|
|
+ action = 'started'
|
|
|
|
+ # In the corner case where test=True and the pool wasn't defined
|
|
|
|
+ # we may get not get our pool in the info dict and that is normal.
|
|
|
|
+ is_running = info.get(name, {}).get('state', 'stopped') == 'running'
|
|
|
|
+ if is_running:
|
|
|
|
+ if updated:
|
|
|
|
+ action = 'built, restarted'
|
|
|
|
+ if not __opts__['test']:
|
|
|
|
+ __salt__['virt.pool_stop'](name, connection=connection, username=username, password=password)
|
|
|
|
+ if not __opts__['test']:
|
|
|
|
+ __salt__['virt.pool_build'](name, connection=connection, username=username, password=password)
|
|
|
|
+ else:
|
|
|
|
+ action = 'already running'
|
|
|
|
+ result = True
|
|
|
|
+
|
|
|
|
+ if not is_running or updated or defined:
|
|
|
|
+ if not __opts__['test']:
|
|
|
|
+ __salt__['virt.pool_start'](name, connection=connection, username=username, password=password)
|
|
|
|
+
|
|
|
|
+ comment = 'Pool {0}'.format(name)
|
|
|
|
+ change = 'Pool'
|
|
|
|
+ if name in ret['changes']:
|
|
|
|
+ comment = '{0},'.format(ret['comment'])
|
|
|
|
+ change = '{0},'.format(ret['changes'][name])
|
|
|
|
+
|
|
|
|
+ if action != 'already running':
|
|
|
|
+ ret['changes'][name] = '{0} {1}'.format(change, action)
|
|
|
|
+
|
|
|
|
+ ret['comment'] = '{0} {1}'.format(comment, action)
|
|
|
|
+ ret['result'] = result
|
|
|
|
+
|
|
|
|
+ except libvirt.libvirtError as err:
|
|
|
|
+ ret['comment'] = err.get_error_message()
|
|
|
|
+ ret['result'] = False
|
|
|
|
+
|
|
|
|
+ return ret
|
|
|
|
+
|
|
|
|
+
|
|
|
|
def pool_deleted(name,
|
|
|
|
purge=False,
|
|
|
|
connection=None,
|
|
|
|
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
|
2020-04-07 14:14:01 +02:00
|
|
|
index d762dcc479..8690154662 100644
|
2020-03-16 16:06:32 +01:00
|
|
|
--- a/tests/unit/modules/test_virt.py
|
|
|
|
+++ b/tests/unit/modules/test_virt.py
|
|
|
|
@@ -1272,6 +1272,32 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
|
|
|
define_mock = MagicMock(return_value=True)
|
|
|
|
self.mock_conn.defineXML = define_mock
|
|
|
|
|
|
|
|
+ # No parameter passed case
|
|
|
|
+ self.assertEqual({
|
|
|
|
+ 'definition': False,
|
|
|
|
+ 'disk': {'attached': [], 'detached': []},
|
|
|
|
+ 'interface': {'attached': [], 'detached': []}
|
|
|
|
+ }, virt.update('my vm'))
|
|
|
|
+
|
|
|
|
+ # Same parameters passed than in default virt.defined state case
|
|
|
|
+ self.assertEqual({
|
|
|
|
+ 'definition': False,
|
|
|
|
+ 'disk': {'attached': [], 'detached': []},
|
|
|
|
+ 'interface': {'attached': [], 'detached': []}
|
|
|
|
+ }, virt.update('my vm',
|
|
|
|
+ cpu=None,
|
|
|
|
+ mem=None,
|
|
|
|
+ disk_profile=None,
|
|
|
|
+ disks=None,
|
|
|
|
+ nic_profile=None,
|
|
|
|
+ interfaces=None,
|
|
|
|
+ graphics=None,
|
|
|
|
+ live=True,
|
|
|
|
+ connection=None,
|
|
|
|
+ username=None,
|
|
|
|
+ password=None,
|
|
|
|
+ boot=None))
|
|
|
|
+
|
|
|
|
# Update vcpus case
|
|
|
|
setvcpus_mock = MagicMock(return_value=0)
|
|
|
|
domain_mock.setVcpusFlags = setvcpus_mock
|
|
|
|
diff --git a/tests/unit/states/test_virt.py b/tests/unit/states/test_virt.py
|
2020-04-07 14:14:01 +02:00
|
|
|
index c50c04b8ab..6727704494 100644
|
2020-03-16 16:06:32 +01:00
|
|
|
--- a/tests/unit/states/test_virt.py
|
|
|
|
+++ b/tests/unit/states/test_virt.py
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -217,6 +217,243 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
2020-03-16 16:06:32 +01:00
|
|
|
organization='SaltStack',
|
|
|
|
expiration_days=700), ret)
|
|
|
|
|
|
|
|
+ def test_defined(self):
|
|
|
|
+ '''
|
|
|
|
+ defined state test cases.
|
|
|
|
+ '''
|
|
|
|
+ ret = {'name': 'myvm',
|
|
|
|
+ 'changes': {},
|
|
|
|
+ 'result': True,
|
|
|
|
+ 'comment': 'myvm is running'}
|
|
|
|
+ with patch.dict(virt.__opts__, {'test': False}):
|
|
|
|
+ # no change test
|
|
|
|
+ init_mock = MagicMock(return_value=True)
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=['myvm']),
|
|
|
|
+ 'virt.update': MagicMock(return_value={'definition': False}),
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': False}},
|
|
|
|
+ 'comment': 'Domain myvm unchanged'})
|
|
|
|
+ self.assertDictEqual(virt.defined('myvm'), ret)
|
|
|
|
+
|
|
|
|
+ # Test defining a guest with connection details
|
|
|
|
+ init_mock.reset_mock()
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=[]),
|
|
|
|
+ 'virt.init': init_mock,
|
|
|
|
+ 'virt.update': MagicMock(side_effect=CommandExecutionError('not found')),
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': True}},
|
|
|
|
+ 'comment': 'Domain myvm defined'})
|
|
|
|
+ disks = [{
|
|
|
|
+ 'name': 'system',
|
|
|
|
+ 'size': 8192,
|
|
|
|
+ 'overlay_image': True,
|
|
|
|
+ 'pool': 'default',
|
|
|
|
+ 'image': '/path/to/image.qcow2'
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ 'name': 'data',
|
|
|
|
+ 'size': 16834
|
|
|
|
+ }]
|
|
|
|
+ ifaces = [{
|
|
|
|
+ 'name': 'eth0',
|
|
|
|
+ 'mac': '01:23:45:67:89:AB'
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ 'name': 'eth1',
|
|
|
|
+ 'type': 'network',
|
|
|
|
+ 'source': 'admin'
|
|
|
|
+ }]
|
|
|
|
+ graphics = {'type': 'spice', 'listen': {'type': 'address', 'address': '192.168.0.1'}}
|
|
|
|
+ self.assertDictEqual(virt.defined('myvm',
|
|
|
|
+ cpu=2,
|
|
|
|
+ mem=2048,
|
|
|
|
+ os_type='linux',
|
|
|
|
+ arch='i686',
|
|
|
|
+ vm_type='qemu',
|
|
|
|
+ disk_profile='prod',
|
|
|
|
+ disks=disks,
|
|
|
|
+ nic_profile='prod',
|
|
|
|
+ interfaces=ifaces,
|
|
|
|
+ graphics=graphics,
|
|
|
|
+ seed=False,
|
|
|
|
+ install=False,
|
|
|
|
+ pub_key='/path/to/key.pub',
|
|
|
|
+ priv_key='/path/to/key',
|
|
|
|
+ connection='someconnection',
|
|
|
|
+ username='libvirtuser',
|
|
|
|
+ password='supersecret'), ret)
|
|
|
|
+ init_mock.assert_called_with('myvm',
|
|
|
|
+ cpu=2,
|
|
|
|
+ mem=2048,
|
|
|
|
+ os_type='linux',
|
|
|
|
+ arch='i686',
|
|
|
|
+ disk='prod',
|
|
|
|
+ disks=disks,
|
|
|
|
+ nic='prod',
|
|
|
|
+ interfaces=ifaces,
|
|
|
|
+ graphics=graphics,
|
|
|
|
+ hypervisor='qemu',
|
|
|
|
+ seed=False,
|
|
|
|
+ boot=None,
|
|
|
|
+ install=False,
|
|
|
|
+ start=False,
|
|
|
|
+ pub_key='/path/to/key.pub',
|
|
|
|
+ priv_key='/path/to/key',
|
|
|
|
+ connection='someconnection',
|
|
|
|
+ username='libvirtuser',
|
|
|
|
+ password='supersecret')
|
|
|
|
+
|
|
|
|
+ # Working update case when running
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=['myvm']),
|
|
|
|
+ 'virt.update': MagicMock(return_value={'definition': True, 'cpu': True})
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': True, 'cpu': True}},
|
|
|
|
+ 'result': True,
|
|
|
|
+ 'comment': 'Domain myvm updated'})
|
|
|
|
+ self.assertDictEqual(virt.defined('myvm', cpu=2), ret)
|
|
|
|
+
|
|
|
|
+ # Working update case when running with boot params
|
|
|
|
+ boot = {
|
|
|
|
+ 'kernel': '/root/f8-i386-vmlinuz',
|
|
|
|
+ 'initrd': '/root/f8-i386-initrd',
|
|
|
|
+ 'cmdline': 'console=ttyS0 ks=http://example.com/f8-i386/os/'
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=['myvm']),
|
|
|
|
+ 'virt.update': MagicMock(return_value={'definition': True, 'cpu': True})
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': True, 'cpu': True}},
|
|
|
|
+ 'result': True,
|
|
|
|
+ 'comment': 'Domain myvm updated'})
|
|
|
|
+ self.assertDictEqual(virt.defined('myvm', boot=boot), ret)
|
|
|
|
+
|
|
|
|
+ # Working update case when stopped
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=['myvm']),
|
|
|
|
+ 'virt.update': MagicMock(return_value={'definition': True})
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': True}},
|
|
|
|
+ 'result': True,
|
|
|
|
+ 'comment': 'Domain myvm updated'})
|
|
|
|
+ self.assertDictEqual(virt.defined('myvm', cpu=2), ret)
|
|
|
|
+
|
|
|
|
+ # Failed live update case
|
|
|
|
+ update_mock = MagicMock(return_value={'definition': True, 'cpu': False, 'errors': ['some error']})
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=['myvm']),
|
|
|
|
+ 'virt.update': update_mock,
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': True, 'cpu': False, 'errors': ['some error']}},
|
|
|
|
+ 'result': True,
|
|
|
|
+ 'comment': 'Domain myvm updated with live update(s) failures'})
|
|
|
|
+ self.assertDictEqual(virt.defined('myvm', cpu=2), ret)
|
|
|
|
+ update_mock.assert_called_with('myvm', cpu=2, mem=None,
|
|
|
|
+ disk_profile=None, disks=None, nic_profile=None, interfaces=None,
|
|
|
|
+ graphics=None, live=True,
|
|
|
|
+ connection=None, username=None, password=None,
|
|
|
|
+ boot=None, test=False)
|
|
|
|
+
|
|
|
|
+ # Failed definition update case
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=['myvm']),
|
|
|
|
+ 'virt.update': MagicMock(side_effect=[self.mock_libvirt.libvirtError('error message')])
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {},
|
|
|
|
+ 'result': False,
|
|
|
|
+ 'comment': 'error message'})
|
|
|
|
+ self.assertDictEqual(virt.defined('myvm', cpu=2), ret)
|
|
|
|
+
|
|
|
|
+ # Test dry-run mode
|
|
|
|
+ with patch.dict(virt.__opts__, {'test': True}):
|
|
|
|
+ # Guest defined case
|
|
|
|
+ init_mock = MagicMock(return_value=True)
|
|
|
|
+ update_mock = MagicMock(side_effect=CommandExecutionError('not found'))
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=[]),
|
|
|
|
+ 'virt.init': init_mock,
|
|
|
|
+ 'virt.update': update_mock,
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': True}},
|
|
|
|
+ 'result': None,
|
|
|
|
+ 'comment': 'Domain myvm defined'})
|
|
|
|
+ disks = [{
|
|
|
|
+ 'name': 'system',
|
|
|
|
+ 'size': 8192,
|
|
|
|
+ 'overlay_image': True,
|
|
|
|
+ 'pool': 'default',
|
|
|
|
+ 'image': '/path/to/image.qcow2'
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ 'name': 'data',
|
|
|
|
+ 'size': 16834
|
|
|
|
+ }]
|
|
|
|
+ ifaces = [{
|
|
|
|
+ 'name': 'eth0',
|
|
|
|
+ 'mac': '01:23:45:67:89:AB'
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ 'name': 'eth1',
|
|
|
|
+ 'type': 'network',
|
|
|
|
+ 'source': 'admin'
|
|
|
|
+ }]
|
|
|
|
+ graphics = {'type': 'spice', 'listen': {'type': 'address', 'address': '192.168.0.1'}}
|
|
|
|
+ self.assertDictEqual(virt.defined('myvm',
|
|
|
|
+ cpu=2,
|
|
|
|
+ mem=2048,
|
|
|
|
+ os_type='linux',
|
|
|
|
+ arch='i686',
|
|
|
|
+ vm_type='qemu',
|
|
|
|
+ disk_profile='prod',
|
|
|
|
+ disks=disks,
|
|
|
|
+ nic_profile='prod',
|
|
|
|
+ interfaces=ifaces,
|
|
|
|
+ graphics=graphics,
|
|
|
|
+ seed=False,
|
|
|
|
+ install=False,
|
|
|
|
+ pub_key='/path/to/key.pub',
|
|
|
|
+ priv_key='/path/to/key',
|
|
|
|
+ connection='someconnection',
|
|
|
|
+ username='libvirtuser',
|
|
|
|
+ password='supersecret'), ret)
|
|
|
|
+ init_mock.assert_not_called()
|
|
|
|
+ update_mock.assert_not_called()
|
|
|
|
+
|
|
|
|
+ # Guest update case
|
|
|
|
+ update_mock = MagicMock(return_value={'definition': True})
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=['myvm']),
|
|
|
|
+ 'virt.update': update_mock
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': True}},
|
|
|
|
+ 'result': None,
|
|
|
|
+ 'comment': 'Domain myvm updated'})
|
|
|
|
+ self.assertDictEqual(virt.defined('myvm', cpu=2), ret)
|
|
|
|
+ update_mock.assert_called_with('myvm', cpu=2, mem=None,
|
|
|
|
+ disk_profile=None, disks=None, nic_profile=None, interfaces=None,
|
|
|
|
+ graphics=None, live=True,
|
|
|
|
+ connection=None, username=None, password=None,
|
|
|
|
+ boot=None, test=True)
|
|
|
|
+
|
|
|
|
+ # No changes case
|
|
|
|
+ update_mock = MagicMock(return_value={'definition': False})
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=['myvm']),
|
|
|
|
+ 'virt.update': update_mock,
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': False}},
|
|
|
|
+ 'result': True,
|
|
|
|
+ 'comment': 'Domain myvm unchanged'})
|
|
|
|
+ self.assertDictEqual(virt.defined('myvm'), ret)
|
|
|
|
+ update_mock.assert_called_with('myvm', cpu=None, mem=None,
|
|
|
|
+ disk_profile=None, disks=None, nic_profile=None, interfaces=None,
|
|
|
|
+ graphics=None, live=True,
|
|
|
|
+ connection=None, username=None, password=None,
|
|
|
|
+ boot=None, test=True)
|
|
|
|
+
|
|
|
|
def test_running(self):
|
|
|
|
'''
|
|
|
|
running state test cases.
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -225,163 +462,369 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
2020-03-16 16:06:32 +01:00
|
|
|
'changes': {},
|
|
|
|
'result': True,
|
|
|
|
'comment': 'myvm is running'}
|
|
|
|
- with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
- 'virt.vm_state': MagicMock(return_value={'myvm': 'stopped'}),
|
|
|
|
- 'virt.start': MagicMock(return_value=0),
|
|
|
|
- }):
|
|
|
|
- ret.update({'changes': {'myvm': 'Domain started'},
|
|
|
|
- 'comment': 'Domain myvm started'})
|
|
|
|
- self.assertDictEqual(virt.running('myvm'), ret)
|
|
|
|
-
|
|
|
|
- init_mock = MagicMock(return_value=True)
|
|
|
|
- with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
- 'virt.vm_state': MagicMock(side_effect=CommandExecutionError('not found')),
|
|
|
|
- 'virt.init': init_mock,
|
|
|
|
- 'virt.start': MagicMock(return_value=0)
|
|
|
|
- }):
|
|
|
|
- ret.update({'changes': {'myvm': 'Domain defined and started'},
|
|
|
|
- 'comment': 'Domain myvm defined and started'})
|
|
|
|
- self.assertDictEqual(virt.running('myvm',
|
|
|
|
- cpu=2,
|
|
|
|
- mem=2048,
|
|
|
|
- image='/path/to/img.qcow2'), ret)
|
|
|
|
- init_mock.assert_called_with('myvm', cpu=2, mem=2048, image='/path/to/img.qcow2',
|
|
|
|
- os_type=None, arch=None, boot=None,
|
|
|
|
- disk=None, disks=None, nic=None, interfaces=None,
|
|
|
|
- graphics=None, hypervisor=None,
|
|
|
|
- seed=True, install=True, pub_key=None, priv_key=None,
|
|
|
|
- connection=None, username=None, password=None)
|
|
|
|
+ with patch.dict(virt.__opts__, {'test': False}):
|
|
|
|
+ # Test starting an existing guest without changing it
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'stopped'}),
|
|
|
|
+ 'virt.start': MagicMock(return_value=0),
|
|
|
|
+ 'virt.update': MagicMock(return_value={'definition': False}),
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=['myvm']),
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'started': True}},
|
|
|
|
+ 'comment': 'Domain myvm started'})
|
|
|
|
+ self.assertDictEqual(virt.running('myvm'), ret)
|
|
|
|
|
|
|
|
- with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
- 'virt.vm_state': MagicMock(side_effect=CommandExecutionError('not found')),
|
|
|
|
- 'virt.init': init_mock,
|
|
|
|
- 'virt.start': MagicMock(return_value=0)
|
|
|
|
- }):
|
|
|
|
- ret.update({'changes': {'myvm': 'Domain defined and started'},
|
|
|
|
- 'comment': 'Domain myvm defined and started'})
|
|
|
|
- disks = [{
|
|
|
|
- 'name': 'system',
|
|
|
|
- 'size': 8192,
|
|
|
|
- 'overlay_image': True,
|
|
|
|
- 'pool': 'default',
|
|
|
|
- 'image': '/path/to/image.qcow2'
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- 'name': 'data',
|
|
|
|
- 'size': 16834
|
|
|
|
- }]
|
|
|
|
- ifaces = [{
|
|
|
|
- 'name': 'eth0',
|
|
|
|
- 'mac': '01:23:45:67:89:AB'
|
|
|
|
- },
|
|
|
|
- {
|
|
|
|
- 'name': 'eth1',
|
|
|
|
- 'type': 'network',
|
|
|
|
- 'source': 'admin'
|
|
|
|
- }]
|
|
|
|
- graphics = {'type': 'spice', 'listen': {'type': 'address', 'address': '192.168.0.1'}}
|
|
|
|
- self.assertDictEqual(virt.running('myvm',
|
|
|
|
- cpu=2,
|
|
|
|
- mem=2048,
|
|
|
|
- os_type='linux',
|
|
|
|
- arch='i686',
|
|
|
|
- vm_type='qemu',
|
|
|
|
- disk_profile='prod',
|
|
|
|
- disks=disks,
|
|
|
|
- nic_profile='prod',
|
|
|
|
- interfaces=ifaces,
|
|
|
|
- graphics=graphics,
|
|
|
|
- seed=False,
|
|
|
|
- install=False,
|
|
|
|
- pub_key='/path/to/key.pub',
|
|
|
|
- priv_key='/path/to/key',
|
|
|
|
+ # Test defining and starting a guest the old way
|
|
|
|
+ init_mock = MagicMock(return_value=True)
|
|
|
|
+ start_mock = MagicMock(return_value=0)
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'stopped'}),
|
|
|
|
+ 'virt.init': init_mock,
|
|
|
|
+ 'virt.start': start_mock,
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=[]),
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': True, 'started': True}},
|
|
|
|
+ 'comment': 'Domain myvm defined and started'})
|
|
|
|
+ self.assertDictEqual(virt.running('myvm',
|
|
|
|
+ cpu=2,
|
|
|
|
+ mem=2048,
|
|
|
|
+ image='/path/to/img.qcow2'), ret)
|
|
|
|
+ init_mock.assert_called_with('myvm', cpu=2, mem=2048,
|
|
|
|
+ os_type=None, arch=None, boot=None,
|
|
|
|
+ disk=None, disks=[{'name': 'system', 'image': '/path/to/img.qcow2'}], nic=None, interfaces=None,
|
|
|
|
+ graphics=None, hypervisor=None, start=False,
|
|
|
|
+ seed=True, install=True, pub_key=None, priv_key=None,
|
|
|
|
+ connection=None, username=None, password=None,)
|
|
|
|
+ start_mock.assert_called_with('myvm', connection=None, username=None, password=None)
|
|
|
|
+
|
|
|
|
+ # Test image parameter with disks with defined image
|
|
|
|
+ init_mock = MagicMock(return_value=True)
|
|
|
|
+ start_mock = MagicMock(return_value=0)
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'stopped'}),
|
|
|
|
+ 'virt.init': init_mock,
|
|
|
|
+ 'virt.start': start_mock,
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=[]),
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': True, 'started': True}},
|
|
|
|
+ 'comment': 'Domain myvm defined and started'})
|
|
|
|
+ disks = [{
|
|
|
|
+ 'name': 'system',
|
|
|
|
+ 'size': 8192,
|
|
|
|
+ 'overlay_image': True,
|
|
|
|
+ 'pool': 'default',
|
|
|
|
+ 'image': '/path/to/image.qcow2'
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ 'name': 'data',
|
|
|
|
+ 'size': 16834
|
|
|
|
+ }]
|
|
|
|
+ self.assertDictEqual(virt.running('myvm',
|
|
|
|
+ cpu=2,
|
|
|
|
+ mem=2048,
|
|
|
|
+ disks=disks,
|
|
|
|
+ image='/path/to/img.qcow2'), ret)
|
|
|
|
+ init_mock.assert_called_with('myvm', cpu=2, mem=2048,
|
|
|
|
+ os_type=None, arch=None, boot=None,
|
|
|
|
+ disk=None, disks=disks, nic=None, interfaces=None,
|
|
|
|
+ graphics=None, hypervisor=None, start=False,
|
|
|
|
+ seed=True, install=True, pub_key=None, priv_key=None,
|
|
|
|
+ connection=None, username=None, password=None,)
|
|
|
|
+ start_mock.assert_called_with('myvm', connection=None, username=None, password=None)
|
|
|
|
+
|
|
|
|
+ # Test image parameter with disks without defined image
|
|
|
|
+ init_mock = MagicMock(return_value=True)
|
|
|
|
+ start_mock = MagicMock(return_value=0)
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'stopped'}),
|
|
|
|
+ 'virt.init': init_mock,
|
|
|
|
+ 'virt.start': start_mock,
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=[]),
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': True, 'started': True}},
|
|
|
|
+ 'comment': 'Domain myvm defined and started'})
|
|
|
|
+ disks = [{
|
|
|
|
+ 'name': 'system',
|
|
|
|
+ 'size': 8192,
|
|
|
|
+ 'overlay_image': True,
|
|
|
|
+ 'pool': 'default',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ 'name': 'data',
|
|
|
|
+ 'size': 16834
|
|
|
|
+ }]
|
|
|
|
+ self.assertDictEqual(virt.running('myvm',
|
|
|
|
+ cpu=2,
|
|
|
|
+ mem=2048,
|
|
|
|
+ disks=disks,
|
|
|
|
+ image='/path/to/img.qcow2'), ret)
|
|
|
|
+ init_mock.assert_called_with('myvm', cpu=2, mem=2048,
|
|
|
|
+ os_type=None, arch=None, boot=None,
|
|
|
|
+ disk=None,
|
|
|
|
+ disks=[{
|
|
|
|
+ 'name': 'system',
|
|
|
|
+ 'size': 8192,
|
|
|
|
+ 'overlay_image': True,
|
|
|
|
+ 'pool': 'default',
|
|
|
|
+ 'image': '/path/to/img.qcow2',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ 'name': 'data',
|
|
|
|
+ 'size': 16834
|
|
|
|
+ }],
|
|
|
|
+ nic=None, interfaces=None,
|
|
|
|
+ graphics=None, hypervisor=None, start=False,
|
|
|
|
+ seed=True, install=True, pub_key=None, priv_key=None,
|
|
|
|
+ connection=None, username=None, password=None,)
|
|
|
|
+ start_mock.assert_called_with('myvm', connection=None, username=None, password=None)
|
|
|
|
+
|
|
|
|
+ # Test defining and starting a guest the new way with connection details
|
|
|
|
+ init_mock.reset_mock()
|
|
|
|
+ start_mock.reset_mock()
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'stopped'}),
|
|
|
|
+ 'virt.init': init_mock,
|
|
|
|
+ 'virt.start': start_mock,
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=[]),
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': True, 'started': True}},
|
|
|
|
+ 'comment': 'Domain myvm defined and started'})
|
|
|
|
+ disks = [{
|
|
|
|
+ 'name': 'system',
|
|
|
|
+ 'size': 8192,
|
|
|
|
+ 'overlay_image': True,
|
|
|
|
+ 'pool': 'default',
|
|
|
|
+ 'image': '/path/to/image.qcow2'
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ 'name': 'data',
|
|
|
|
+ 'size': 16834
|
|
|
|
+ }]
|
|
|
|
+ ifaces = [{
|
|
|
|
+ 'name': 'eth0',
|
|
|
|
+ 'mac': '01:23:45:67:89:AB'
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ 'name': 'eth1',
|
|
|
|
+ 'type': 'network',
|
|
|
|
+ 'source': 'admin'
|
|
|
|
+ }]
|
|
|
|
+ graphics = {'type': 'spice', 'listen': {'type': 'address', 'address': '192.168.0.1'}}
|
|
|
|
+ self.assertDictEqual(virt.running('myvm',
|
|
|
|
+ cpu=2,
|
|
|
|
+ mem=2048,
|
|
|
|
+ os_type='linux',
|
|
|
|
+ arch='i686',
|
|
|
|
+ vm_type='qemu',
|
|
|
|
+ disk_profile='prod',
|
|
|
|
+ disks=disks,
|
|
|
|
+ nic_profile='prod',
|
|
|
|
+ interfaces=ifaces,
|
|
|
|
+ graphics=graphics,
|
|
|
|
+ seed=False,
|
|
|
|
+ install=False,
|
|
|
|
+ pub_key='/path/to/key.pub',
|
|
|
|
+ priv_key='/path/to/key',
|
|
|
|
+ connection='someconnection',
|
|
|
|
+ username='libvirtuser',
|
|
|
|
+ password='supersecret'), ret)
|
|
|
|
+ init_mock.assert_called_with('myvm',
|
|
|
|
+ cpu=2,
|
|
|
|
+ mem=2048,
|
|
|
|
+ os_type='linux',
|
|
|
|
+ arch='i686',
|
|
|
|
+ disk='prod',
|
|
|
|
+ disks=disks,
|
|
|
|
+ nic='prod',
|
|
|
|
+ interfaces=ifaces,
|
|
|
|
+ graphics=graphics,
|
|
|
|
+ hypervisor='qemu',
|
|
|
|
+ seed=False,
|
|
|
|
+ boot=None,
|
|
|
|
+ install=False,
|
|
|
|
+ start=False,
|
|
|
|
+ pub_key='/path/to/key.pub',
|
|
|
|
+ priv_key='/path/to/key',
|
|
|
|
+ connection='someconnection',
|
|
|
|
+ username='libvirtuser',
|
|
|
|
+ password='supersecret')
|
|
|
|
+ start_mock.assert_called_with('myvm',
|
|
|
|
connection='someconnection',
|
|
|
|
username='libvirtuser',
|
|
|
|
- password='supersecret'), ret)
|
|
|
|
- init_mock.assert_called_with('myvm',
|
|
|
|
- cpu=2,
|
|
|
|
- mem=2048,
|
|
|
|
- os_type='linux',
|
|
|
|
- arch='i686',
|
|
|
|
- image=None,
|
|
|
|
- disk='prod',
|
|
|
|
- disks=disks,
|
|
|
|
- nic='prod',
|
|
|
|
- interfaces=ifaces,
|
|
|
|
- graphics=graphics,
|
|
|
|
- hypervisor='qemu',
|
|
|
|
- seed=False,
|
|
|
|
- boot=None,
|
|
|
|
- install=False,
|
|
|
|
- pub_key='/path/to/key.pub',
|
|
|
|
- priv_key='/path/to/key',
|
|
|
|
- connection='someconnection',
|
|
|
|
- username='libvirtuser',
|
|
|
|
- password='supersecret')
|
|
|
|
+ password='supersecret')
|
|
|
|
|
|
|
|
- with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
- 'virt.vm_state': MagicMock(return_value={'myvm': 'stopped'}),
|
|
|
|
- 'virt.start': MagicMock(side_effect=[self.mock_libvirt.libvirtError('libvirt error msg')])
|
|
|
|
- }):
|
|
|
|
- ret.update({'changes': {}, 'result': False, 'comment': 'libvirt error msg'})
|
|
|
|
- self.assertDictEqual(virt.running('myvm'), ret)
|
|
|
|
+ # Test with existing guest, but start raising an error
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'stopped'}),
|
|
|
|
+ 'virt.update': MagicMock(return_value={'definition': False}),
|
|
|
|
+ 'virt.start': MagicMock(side_effect=[self.mock_libvirt.libvirtError('libvirt error msg')]),
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=['myvm']),
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {}}, 'result': False, 'comment': 'libvirt error msg'})
|
|
|
|
+ self.assertDictEqual(virt.running('myvm'), ret)
|
|
|
|
|
|
|
|
- # Working update case when running
|
|
|
|
- with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
- 'virt.vm_state': MagicMock(return_value={'myvm': 'running'}),
|
|
|
|
- 'virt.update': MagicMock(return_value={'definition': True, 'cpu': True})
|
|
|
|
- }):
|
|
|
|
- ret.update({'changes': {'myvm': {'definition': True, 'cpu': True}},
|
|
|
|
- 'result': True,
|
|
|
|
- 'comment': 'Domain myvm updated, restart to fully apply the changes'})
|
|
|
|
- self.assertDictEqual(virt.running('myvm', update=True, cpu=2), ret)
|
|
|
|
-
|
|
|
|
- # Working update case when running with boot params
|
|
|
|
- boot = {
|
|
|
|
- 'kernel': '/root/f8-i386-vmlinuz',
|
|
|
|
- 'initrd': '/root/f8-i386-initrd',
|
|
|
|
- 'cmdline': 'console=ttyS0 ks=http://example.com/f8-i386/os/'
|
|
|
|
- }
|
|
|
|
+ # Working update case when running
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'running'}),
|
|
|
|
+ 'virt.update': MagicMock(return_value={'definition': True, 'cpu': True}),
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=['myvm']),
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': True, 'cpu': True}},
|
|
|
|
+ 'result': True,
|
|
|
|
+ 'comment': 'Domain myvm updated'})
|
|
|
|
+ self.assertDictEqual(virt.running('myvm', cpu=2, update=True), ret)
|
|
|
|
+
|
|
|
|
+ # Working update case when running with boot params
|
|
|
|
+ boot = {
|
|
|
|
+ 'kernel': '/root/f8-i386-vmlinuz',
|
|
|
|
+ 'initrd': '/root/f8-i386-initrd',
|
|
|
|
+ 'cmdline': 'console=ttyS0 ks=http://example.com/f8-i386/os/'
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
- 'virt.vm_state': MagicMock(return_value={'myvm': 'running'}),
|
|
|
|
- 'virt.update': MagicMock(return_value={'definition': True, 'cpu': True})
|
|
|
|
- }):
|
|
|
|
- ret.update({'changes': {'myvm': {'definition': True, 'cpu': True}},
|
|
|
|
- 'result': True,
|
|
|
|
- 'comment': 'Domain myvm updated, restart to fully apply the changes'})
|
|
|
|
- self.assertDictEqual(virt.running('myvm', update=True, boot=boot), ret)
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'running'}),
|
|
|
|
+ 'virt.update': MagicMock(return_value={'definition': True, 'cpu': True}),
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=['myvm']),
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': True, 'cpu': True}},
|
|
|
|
+ 'result': True,
|
|
|
|
+ 'comment': 'Domain myvm updated'})
|
|
|
|
+ self.assertDictEqual(virt.running('myvm', boot=boot, update=True), ret)
|
|
|
|
|
|
|
|
- # Working update case when stopped
|
|
|
|
- with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
- 'virt.vm_state': MagicMock(return_value={'myvm': 'stopped'}),
|
|
|
|
- 'virt.start': MagicMock(return_value=0),
|
|
|
|
- 'virt.update': MagicMock(return_value={'definition': True})
|
|
|
|
- }):
|
|
|
|
- ret.update({'changes': {'myvm': 'Domain updated and started'},
|
|
|
|
- 'result': True,
|
|
|
|
- 'comment': 'Domain myvm updated and started'})
|
|
|
|
- self.assertDictEqual(virt.running('myvm', update=True, cpu=2), ret)
|
|
|
|
+ # Working update case when stopped
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'stopped'}),
|
|
|
|
+ 'virt.start': MagicMock(return_value=0),
|
|
|
|
+ 'virt.update': MagicMock(return_value={'definition': True}),
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=['myvm']),
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': True, 'started': True}},
|
|
|
|
+ 'result': True,
|
|
|
|
+ 'comment': 'Domain myvm updated and started'})
|
|
|
|
+ self.assertDictEqual(virt.running('myvm', cpu=2, update=True), ret)
|
|
|
|
|
|
|
|
- # Failed live update case
|
|
|
|
- with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
- 'virt.vm_state': MagicMock(return_value={'myvm': 'running'}),
|
|
|
|
- 'virt.update': MagicMock(return_value={'definition': True, 'cpu': False, 'errors': ['some error']})
|
|
|
|
- }):
|
|
|
|
- ret.update({'changes': {'myvm': {'definition': True, 'cpu': False, 'errors': ['some error']}},
|
|
|
|
- 'result': True,
|
|
|
|
- 'comment': 'Domain myvm updated, but some live update(s) failed'})
|
|
|
|
- self.assertDictEqual(virt.running('myvm', update=True, cpu=2), ret)
|
|
|
|
+ # Failed live update case
|
|
|
|
+ update_mock = MagicMock(return_value={'definition': True, 'cpu': False, 'errors': ['some error']})
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'running'}),
|
|
|
|
+ 'virt.update': update_mock,
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=['myvm']),
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': True, 'cpu': False, 'errors': ['some error']}},
|
|
|
|
+ 'result': True,
|
|
|
|
+ 'comment': 'Domain myvm updated with live update(s) failures'})
|
|
|
|
+ self.assertDictEqual(virt.running('myvm', cpu=2, update=True), ret)
|
|
|
|
+ update_mock.assert_called_with('myvm', cpu=2, mem=None,
|
|
|
|
+ disk_profile=None, disks=None, nic_profile=None, interfaces=None,
|
|
|
|
+ graphics=None, live=True,
|
|
|
|
+ connection=None, username=None, password=None,
|
|
|
|
+ boot=None, test=False)
|
|
|
|
+
|
|
|
|
+ # Failed definition update case
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'running'}),
|
|
|
|
+ 'virt.update': MagicMock(side_effect=[self.mock_libvirt.libvirtError('error message')]),
|
|
|
|
+ 'virt.list_domains': MagicMock(return_value=['myvm']),
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {},
|
|
|
|
+ 'result': False,
|
|
|
|
+ 'comment': 'error message'})
|
|
|
|
+ self.assertDictEqual(virt.running('myvm', cpu=2, update=True), ret)
|
|
|
|
|
|
|
|
- # Failed definition update case
|
|
|
|
- with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
- 'virt.vm_state': MagicMock(return_value={'myvm': 'running'}),
|
|
|
|
- 'virt.update': MagicMock(side_effect=[self.mock_libvirt.libvirtError('error message')])
|
|
|
|
- }):
|
|
|
|
- ret.update({'changes': {},
|
|
|
|
- 'result': False,
|
|
|
|
- 'comment': 'error message'})
|
|
|
|
- self.assertDictEqual(virt.running('myvm', update=True, cpu=2), ret)
|
|
|
|
+ # Test dry-run mode
|
|
|
|
+ with patch.dict(virt.__opts__, {'test': True}):
|
|
|
|
+ # Guest defined case
|
|
|
|
+ init_mock = MagicMock(return_value=True)
|
|
|
|
+ start_mock = MagicMock(return_value=0)
|
|
|
|
+ list_mock = MagicMock(return_value=[])
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'stopped'}),
|
|
|
|
+ 'virt.init': init_mock,
|
|
|
|
+ 'virt.start': start_mock,
|
|
|
|
+ 'virt.list_domains': list_mock,
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': True, 'started': True}},
|
|
|
|
+ 'result': None,
|
|
|
|
+ 'comment': 'Domain myvm defined and started'})
|
|
|
|
+ disks = [{
|
|
|
|
+ 'name': 'system',
|
|
|
|
+ 'size': 8192,
|
|
|
|
+ 'overlay_image': True,
|
|
|
|
+ 'pool': 'default',
|
|
|
|
+ 'image': '/path/to/image.qcow2'
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ 'name': 'data',
|
|
|
|
+ 'size': 16834
|
|
|
|
+ }]
|
|
|
|
+ ifaces = [{
|
|
|
|
+ 'name': 'eth0',
|
|
|
|
+ 'mac': '01:23:45:67:89:AB'
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ 'name': 'eth1',
|
|
|
|
+ 'type': 'network',
|
|
|
|
+ 'source': 'admin'
|
|
|
|
+ }]
|
|
|
|
+ graphics = {'type': 'spice', 'listen': {'type': 'address', 'address': '192.168.0.1'}}
|
|
|
|
+ self.assertDictEqual(virt.running('myvm',
|
|
|
|
+ cpu=2,
|
|
|
|
+ mem=2048,
|
|
|
|
+ os_type='linux',
|
|
|
|
+ arch='i686',
|
|
|
|
+ vm_type='qemu',
|
|
|
|
+ disk_profile='prod',
|
|
|
|
+ disks=disks,
|
|
|
|
+ nic_profile='prod',
|
|
|
|
+ interfaces=ifaces,
|
|
|
|
+ graphics=graphics,
|
|
|
|
+ seed=False,
|
|
|
|
+ install=False,
|
|
|
|
+ pub_key='/path/to/key.pub',
|
|
|
|
+ priv_key='/path/to/key',
|
|
|
|
+ connection='someconnection',
|
|
|
|
+ username='libvirtuser',
|
|
|
|
+ password='supersecret'), ret)
|
|
|
|
+ init_mock.assert_not_called()
|
|
|
|
+ start_mock.assert_not_called()
|
|
|
|
+
|
|
|
|
+ # Guest update case
|
|
|
|
+ update_mock = MagicMock(return_value={'definition': True})
|
|
|
|
+ start_mock = MagicMock(return_value=0)
|
|
|
|
+ list_mock = MagicMock(return_value=['myvm'])
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'stopped'}),
|
|
|
|
+ 'virt.start': start_mock,
|
|
|
|
+ 'virt.update': update_mock,
|
|
|
|
+ 'virt.list_domains': list_mock,
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': True, 'started': True}},
|
|
|
|
+ 'result': None,
|
|
|
|
+ 'comment': 'Domain myvm updated and started'})
|
|
|
|
+ self.assertDictEqual(virt.running('myvm', cpu=2, update=True), ret)
|
|
|
|
+ update_mock.assert_called_with('myvm', cpu=2, mem=None,
|
|
|
|
+ disk_profile=None, disks=None, nic_profile=None, interfaces=None,
|
|
|
|
+ graphics=None, live=True,
|
|
|
|
+ connection=None, username=None, password=None,
|
|
|
|
+ boot=None, test=True)
|
|
|
|
+ start_mock.assert_not_called()
|
|
|
|
+
|
|
|
|
+ # No changes case
|
|
|
|
+ update_mock = MagicMock(return_value={'definition': False})
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'running'}),
|
|
|
|
+ 'virt.update': update_mock,
|
|
|
|
+ 'virt.list_domains': list_mock,
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'myvm': {'definition': False}},
|
|
|
|
+ 'result': True,
|
|
|
|
+ 'comment': 'Domain myvm exists and is running'})
|
|
|
|
+ self.assertDictEqual(virt.running('myvm', update=True), ret)
|
|
|
|
+ update_mock.assert_called_with('myvm', cpu=None, mem=None,
|
|
|
|
+ disk_profile=None, disks=None, nic_profile=None, interfaces=None,
|
|
|
|
+ graphics=None, live=True,
|
|
|
|
+ connection=None, username=None, password=None,
|
|
|
|
+ boot=None, test=True)
|
|
|
|
|
|
|
|
def test_stopped(self):
|
|
|
|
'''
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -599,92 +1042,506 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
2020-03-16 16:06:32 +01:00
|
|
|
ret.update({'changes': {}, 'result': False, 'comment': 'No changes had happened'})
|
|
|
|
self.assertDictEqual(virt.rebooted('myvm'), ret)
|
|
|
|
|
|
|
|
+ def test_network_defined(self):
|
|
|
|
+ '''
|
|
|
|
+ network_defined state test cases.
|
|
|
|
+ '''
|
|
|
|
+ ret = {'name': 'mynet', 'changes': {}, 'result': True, 'comment': ''}
|
|
|
|
+ with patch.dict(virt.__opts__, {'test': False}):
|
|
|
|
+ define_mock = MagicMock(return_value=True)
|
|
|
|
+ # Non-existing network case
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.network_info': MagicMock(side_effect=[{}, {'mynet': {'active': False}}]),
|
|
|
|
+ 'virt.network_define': define_mock,
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'mynet': 'Network defined'},
|
|
|
|
+ 'comment': 'Network mynet defined'})
|
|
|
|
+ self.assertDictEqual(virt.network_defined('mynet',
|
|
|
|
+ 'br2',
|
|
|
|
+ 'bridge',
|
|
|
|
+ vport='openvswitch',
|
|
|
|
+ tag=180,
|
|
|
|
+ ipv4_config={
|
|
|
|
+ 'cidr': '192.168.2.0/24',
|
|
|
|
+ 'dhcp_ranges': [
|
|
|
|
+ {'start': '192.168.2.10', 'end': '192.168.2.25'},
|
|
|
|
+ {'start': '192.168.2.110', 'end': '192.168.2.125'},
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ ipv6_config={
|
|
|
|
+ 'cidr': '2001:db8:ca2:2::1/64',
|
|
|
|
+ 'dhcp_ranges': [
|
|
|
|
+ {'start': '2001:db8:ca2:1::10', 'end': '2001:db8:ca2::1f'},
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ autostart=False,
|
|
|
|
+ connection='myconnection',
|
|
|
|
+ username='user',
|
|
|
|
+ password='secret'), ret)
|
|
|
|
+ define_mock.assert_called_with('mynet',
|
|
|
|
+ 'br2',
|
|
|
|
+ 'bridge',
|
|
|
|
+ vport='openvswitch',
|
|
|
|
+ tag=180,
|
|
|
|
+ autostart=False,
|
|
|
|
+ start=False,
|
|
|
|
+ ipv4_config={
|
|
|
|
+ 'cidr': '192.168.2.0/24',
|
|
|
|
+ 'dhcp_ranges': [
|
|
|
|
+ {'start': '192.168.2.10', 'end': '192.168.2.25'},
|
|
|
|
+ {'start': '192.168.2.110', 'end': '192.168.2.125'},
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ ipv6_config={
|
|
|
|
+ 'cidr': '2001:db8:ca2:2::1/64',
|
|
|
|
+ 'dhcp_ranges': [
|
|
|
|
+ {'start': '2001:db8:ca2:1::10', 'end': '2001:db8:ca2::1f'},
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ connection='myconnection',
|
|
|
|
+ username='user',
|
|
|
|
+ password='secret')
|
|
|
|
+
|
|
|
|
+ # Case where there is nothing to be done
|
|
|
|
+ define_mock.reset_mock()
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.network_info': MagicMock(return_value={'mynet': {'active': True}}),
|
|
|
|
+ 'virt.network_define': define_mock,
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {}, 'comment': 'Network mynet exists'})
|
|
|
|
+ self.assertDictEqual(virt.network_defined('mynet', 'br2', 'bridge'), ret)
|
|
|
|
+
|
|
|
|
+ # Error case
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.network_info': MagicMock(return_value={}),
|
|
|
|
+ 'virt.network_define': MagicMock(side_effect=self.mock_libvirt.libvirtError('Some error'))
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {}, 'comment': 'Some error', 'result': False})
|
|
|
|
+ self.assertDictEqual(virt.network_defined('mynet', 'br2', 'bridge'), ret)
|
|
|
|
+
|
|
|
|
+ # Test cases with __opt__['test'] set to True
|
|
|
|
+ with patch.dict(virt.__opts__, {'test': True}):
|
|
|
|
+ ret.update({'result': None})
|
|
|
|
+
|
|
|
|
+ # Non-existing network case
|
|
|
|
+ define_mock.reset_mock()
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.network_info': MagicMock(return_value={}),
|
|
|
|
+ 'virt.network_define': define_mock,
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'mynet': 'Network defined'},
|
|
|
|
+ 'comment': 'Network mynet defined'})
|
|
|
|
+ self.assertDictEqual(virt.network_defined('mynet',
|
|
|
|
+ 'br2',
|
|
|
|
+ 'bridge',
|
|
|
|
+ vport='openvswitch',
|
|
|
|
+ tag=180,
|
|
|
|
+ ipv4_config={
|
|
|
|
+ 'cidr': '192.168.2.0/24',
|
|
|
|
+ 'dhcp_ranges': [
|
|
|
|
+ {'start': '192.168.2.10', 'end': '192.168.2.25'},
|
|
|
|
+ {'start': '192.168.2.110', 'end': '192.168.2.125'},
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ ipv6_config={
|
|
|
|
+ 'cidr': '2001:db8:ca2:2::1/64',
|
|
|
|
+ 'dhcp_ranges': [
|
|
|
|
+ {'start': '2001:db8:ca2:1::10', 'end': '2001:db8:ca2::1f'},
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ autostart=False,
|
|
|
|
+ connection='myconnection',
|
|
|
|
+ username='user',
|
|
|
|
+ password='secret'), ret)
|
|
|
|
+ define_mock.assert_not_called()
|
|
|
|
+
|
|
|
|
+ # Case where there is nothing to be done
|
|
|
|
+ define_mock.reset_mock()
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.network_info': MagicMock(return_value={'mynet': {'active': True}}),
|
|
|
|
+ 'virt.network_define': define_mock,
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {}, 'comment': 'Network mynet exists', 'result': True})
|
|
|
|
+ self.assertDictEqual(virt.network_defined('mynet', 'br2', 'bridge'), ret)
|
|
|
|
+
|
|
|
|
+ # Error case
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.network_info': MagicMock(side_effect=self.mock_libvirt.libvirtError('Some error'))
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {}, 'comment': 'Some error', 'result': False})
|
|
|
|
+ self.assertDictEqual(virt.network_defined('mynet', 'br2', 'bridge'), ret)
|
|
|
|
+
|
|
|
|
def test_network_running(self):
|
|
|
|
'''
|
|
|
|
network_running state test cases.
|
|
|
|
'''
|
|
|
|
ret = {'name': 'mynet', 'changes': {}, 'result': True, 'comment': ''}
|
|
|
|
- define_mock = MagicMock(return_value=True)
|
|
|
|
- with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
- 'virt.network_info': MagicMock(return_value={}),
|
|
|
|
- 'virt.network_define': define_mock
|
|
|
|
- }):
|
|
|
|
- ret.update({'changes': {'mynet': 'Network defined and started'},
|
|
|
|
- 'comment': 'Network mynet defined and started'})
|
|
|
|
- self.assertDictEqual(virt.network_running('mynet',
|
|
|
|
- 'br2',
|
|
|
|
- 'bridge',
|
|
|
|
- vport='openvswitch',
|
|
|
|
- tag=180,
|
|
|
|
- ipv4_config={
|
|
|
|
- 'cidr': '192.168.2.0/24',
|
|
|
|
- 'dhcp_ranges': [
|
|
|
|
- {'start': '192.168.2.10', 'end': '192.168.2.25'},
|
|
|
|
- {'start': '192.168.2.110', 'end': '192.168.2.125'},
|
|
|
|
- ]
|
|
|
|
- },
|
|
|
|
- ipv6_config={
|
|
|
|
- 'cidr': '2001:db8:ca2:2::1/64',
|
|
|
|
- 'dhcp_ranges': [
|
|
|
|
- {'start': '2001:db8:ca2:1::10', 'end': '2001:db8:ca2::1f'},
|
|
|
|
- ]
|
|
|
|
- },
|
|
|
|
- autostart=False,
|
|
|
|
- connection='myconnection',
|
|
|
|
- username='user',
|
|
|
|
- password='secret'), ret)
|
|
|
|
- define_mock.assert_called_with('mynet',
|
|
|
|
- 'br2',
|
|
|
|
- 'bridge',
|
|
|
|
- vport='openvswitch',
|
|
|
|
- tag=180,
|
|
|
|
- autostart=False,
|
|
|
|
- start=True,
|
|
|
|
- ipv4_config={
|
|
|
|
- 'cidr': '192.168.2.0/24',
|
|
|
|
- 'dhcp_ranges': [
|
|
|
|
- {'start': '192.168.2.10', 'end': '192.168.2.25'},
|
|
|
|
- {'start': '192.168.2.110', 'end': '192.168.2.125'},
|
|
|
|
- ]
|
|
|
|
- },
|
|
|
|
- ipv6_config={
|
|
|
|
- 'cidr': '2001:db8:ca2:2::1/64',
|
|
|
|
- 'dhcp_ranges': [
|
|
|
|
- {'start': '2001:db8:ca2:1::10', 'end': '2001:db8:ca2::1f'},
|
|
|
|
- ]
|
|
|
|
- },
|
|
|
|
- connection='myconnection',
|
|
|
|
- username='user',
|
|
|
|
- password='secret')
|
|
|
|
+ with patch.dict(virt.__opts__, {'test': False}):
|
|
|
|
+ define_mock = MagicMock(return_value=True)
|
|
|
|
+ start_mock = MagicMock(return_value=True)
|
|
|
|
+ # Non-existing network case
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.network_info': MagicMock(side_effect=[{}, {'mynet': {'active': False}}]),
|
|
|
|
+ 'virt.network_define': define_mock,
|
|
|
|
+ 'virt.network_start': start_mock,
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'mynet': 'Network defined and started'},
|
|
|
|
+ 'comment': 'Network mynet defined and started'})
|
|
|
|
+ self.assertDictEqual(virt.network_running('mynet',
|
|
|
|
+ 'br2',
|
|
|
|
+ 'bridge',
|
|
|
|
+ vport='openvswitch',
|
|
|
|
+ tag=180,
|
|
|
|
+ ipv4_config={
|
|
|
|
+ 'cidr': '192.168.2.0/24',
|
|
|
|
+ 'dhcp_ranges': [
|
|
|
|
+ {'start': '192.168.2.10', 'end': '192.168.2.25'},
|
|
|
|
+ {'start': '192.168.2.110', 'end': '192.168.2.125'},
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ ipv6_config={
|
|
|
|
+ 'cidr': '2001:db8:ca2:2::1/64',
|
|
|
|
+ 'dhcp_ranges': [
|
|
|
|
+ {'start': '2001:db8:ca2:1::10', 'end': '2001:db8:ca2::1f'},
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ autostart=False,
|
|
|
|
+ connection='myconnection',
|
|
|
|
+ username='user',
|
|
|
|
+ password='secret'), ret)
|
|
|
|
+ define_mock.assert_called_with('mynet',
|
|
|
|
+ 'br2',
|
|
|
|
+ 'bridge',
|
|
|
|
+ vport='openvswitch',
|
|
|
|
+ tag=180,
|
|
|
|
+ autostart=False,
|
|
|
|
+ start=False,
|
|
|
|
+ ipv4_config={
|
|
|
|
+ 'cidr': '192.168.2.0/24',
|
|
|
|
+ 'dhcp_ranges': [
|
|
|
|
+ {'start': '192.168.2.10', 'end': '192.168.2.25'},
|
|
|
|
+ {'start': '192.168.2.110', 'end': '192.168.2.125'},
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ ipv6_config={
|
|
|
|
+ 'cidr': '2001:db8:ca2:2::1/64',
|
|
|
|
+ 'dhcp_ranges': [
|
|
|
|
+ {'start': '2001:db8:ca2:1::10', 'end': '2001:db8:ca2::1f'},
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ connection='myconnection',
|
|
|
|
+ username='user',
|
|
|
|
+ password='secret')
|
|
|
|
+ start_mock.assert_called_with('mynet',
|
|
|
|
+ connection='myconnection',
|
|
|
|
+ username='user',
|
|
|
|
+ password='secret')
|
|
|
|
|
|
|
|
- with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
- 'virt.network_info': MagicMock(return_value={'mynet': {'active': True}}),
|
|
|
|
- 'virt.network_define': define_mock,
|
|
|
|
- }):
|
|
|
|
- ret.update({'changes': {}, 'comment': 'Network mynet exists and is running'})
|
|
|
|
- self.assertDictEqual(virt.network_running('mynet', 'br2', 'bridge'), ret)
|
|
|
|
+ # Case where there is nothing to be done
|
|
|
|
+ define_mock.reset_mock()
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.network_info': MagicMock(return_value={'mynet': {'active': True}}),
|
|
|
|
+ 'virt.network_define': define_mock,
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {}, 'comment': 'Network mynet exists and is running'})
|
|
|
|
+ self.assertDictEqual(virt.network_running('mynet', 'br2', 'bridge'), ret)
|
|
|
|
|
|
|
|
- start_mock = MagicMock(return_value=True)
|
|
|
|
- with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
- 'virt.network_info': MagicMock(return_value={'mynet': {'active': False}}),
|
|
|
|
- 'virt.network_start': start_mock,
|
|
|
|
- 'virt.network_define': define_mock,
|
|
|
|
- }):
|
|
|
|
- ret.update({'changes': {'mynet': 'Network started'}, 'comment': 'Network mynet started'})
|
|
|
|
- self.assertDictEqual(virt.network_running('mynet',
|
|
|
|
- 'br2',
|
|
|
|
- 'bridge',
|
|
|
|
+ # Network existing and stopped case
|
|
|
|
+ start_mock = MagicMock(return_value=True)
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.network_info': MagicMock(return_value={'mynet': {'active': False}}),
|
|
|
|
+ 'virt.network_start': start_mock,
|
|
|
|
+ 'virt.network_define': define_mock,
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'mynet': 'Network started'}, 'comment': 'Network mynet exists and started'})
|
|
|
|
+ self.assertDictEqual(virt.network_running('mynet',
|
|
|
|
+ 'br2',
|
|
|
|
+ 'bridge',
|
|
|
|
+ connection='myconnection',
|
|
|
|
+ username='user',
|
|
|
|
+ password='secret'), ret)
|
|
|
|
+ start_mock.assert_called_with('mynet', connection='myconnection', username='user', password='secret')
|
|
|
|
+
|
|
|
|
+ # Error case
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.network_info': MagicMock(return_value={}),
|
|
|
|
+ 'virt.network_define': MagicMock(side_effect=self.mock_libvirt.libvirtError('Some error'))
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {}, 'comment': 'Some error', 'result': False})
|
|
|
|
+ self.assertDictEqual(virt.network_running('mynet', 'br2', 'bridge'), ret)
|
|
|
|
+
|
|
|
|
+ # Test cases with __opt__['test'] set to True
|
|
|
|
+ with patch.dict(virt.__opts__, {'test': True}):
|
|
|
|
+ ret.update({'result': None})
|
|
|
|
+
|
|
|
|
+ # Non-existing network case
|
|
|
|
+ define_mock.reset_mock()
|
|
|
|
+ start_mock.reset_mock()
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.network_info': MagicMock(return_value={}),
|
|
|
|
+ 'virt.network_define': define_mock,
|
|
|
|
+ 'virt.network_start': start_mock,
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'mynet': 'Network defined and started'},
|
|
|
|
+ 'comment': 'Network mynet defined and started'})
|
|
|
|
+ self.assertDictEqual(virt.network_running('mynet',
|
|
|
|
+ 'br2',
|
|
|
|
+ 'bridge',
|
|
|
|
+ vport='openvswitch',
|
|
|
|
+ tag=180,
|
|
|
|
+ ipv4_config={
|
|
|
|
+ 'cidr': '192.168.2.0/24',
|
|
|
|
+ 'dhcp_ranges': [
|
|
|
|
+ {'start': '192.168.2.10', 'end': '192.168.2.25'},
|
|
|
|
+ {'start': '192.168.2.110', 'end': '192.168.2.125'},
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ ipv6_config={
|
|
|
|
+ 'cidr': '2001:db8:ca2:2::1/64',
|
|
|
|
+ 'dhcp_ranges': [
|
|
|
|
+ {'start': '2001:db8:ca2:1::10', 'end': '2001:db8:ca2::1f'},
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ autostart=False,
|
|
|
|
+ connection='myconnection',
|
|
|
|
+ username='user',
|
|
|
|
+ password='secret'), ret)
|
|
|
|
+ define_mock.assert_not_called()
|
|
|
|
+ start_mock.assert_not_called()
|
|
|
|
+
|
|
|
|
+ # Case where there is nothing to be done
|
|
|
|
+ define_mock.reset_mock()
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.network_info': MagicMock(return_value={'mynet': {'active': True}}),
|
|
|
|
+ 'virt.network_define': define_mock,
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {}, 'comment': 'Network mynet exists and is running'})
|
|
|
|
+ self.assertDictEqual(virt.network_running('mynet', 'br2', 'bridge'), ret)
|
|
|
|
+
|
|
|
|
+ # Network existing and stopped case
|
|
|
|
+ start_mock = MagicMock(return_value=True)
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.network_info': MagicMock(return_value={'mynet': {'active': False}}),
|
|
|
|
+ 'virt.network_start': start_mock,
|
|
|
|
+ 'virt.network_define': define_mock,
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'mynet': 'Network started'}, 'comment': 'Network mynet exists and started'})
|
|
|
|
+ self.assertDictEqual(virt.network_running('mynet',
|
|
|
|
+ 'br2',
|
|
|
|
+ 'bridge',
|
|
|
|
+ connection='myconnection',
|
|
|
|
+ username='user',
|
|
|
|
+ password='secret'), ret)
|
|
|
|
+ start_mock.assert_not_called()
|
|
|
|
+
|
|
|
|
+ # Error case
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.network_info': MagicMock(side_effect=self.mock_libvirt.libvirtError('Some error'))
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {}, 'comment': 'Some error', 'result': False})
|
|
|
|
+ self.assertDictEqual(virt.network_running('mynet', 'br2', 'bridge'), ret)
|
|
|
|
+
|
|
|
|
+ def test_pool_defined(self):
|
|
|
|
+ '''
|
|
|
|
+ pool_defined state test cases.
|
|
|
|
+ '''
|
|
|
|
+ ret = {'name': 'mypool', 'changes': {}, 'result': True, 'comment': ''}
|
|
|
|
+ mocks = {mock: MagicMock(return_value=True) for mock in ['define', 'autostart', 'build']}
|
|
|
|
+ with patch.dict(virt.__opts__, {'test': False}):
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.pool_info': MagicMock(side_effect=[{}, {'mypool': {'state': 'stopped', 'autostart': True}}]),
|
|
|
|
+ 'virt.pool_define': mocks['define'],
|
|
|
|
+ 'virt.pool_build': mocks['build'],
|
|
|
|
+ 'virt.pool_set_autostart': mocks['autostart']
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'mypool': 'Pool defined, marked for autostart'},
|
|
|
|
+ 'comment': 'Pool mypool defined, marked for autostart'})
|
|
|
|
+ self.assertDictEqual(virt.pool_defined('mypool',
|
|
|
|
+ ptype='logical',
|
|
|
|
+ target='/dev/base',
|
|
|
|
+ permissions={'mode': '0770',
|
|
|
|
+ 'owner': 1000,
|
|
|
|
+ 'group': 100,
|
|
|
|
+ 'label': 'seclabel'},
|
|
|
|
+ source={'devices': [{'path': '/dev/sda'}]},
|
|
|
|
+ transient=True,
|
|
|
|
+ autostart=True,
|
|
|
|
+ connection='myconnection',
|
|
|
|
+ username='user',
|
|
|
|
+ password='secret'), ret)
|
|
|
|
+ mocks['define'].assert_called_with('mypool',
|
|
|
|
+ ptype='logical',
|
|
|
|
+ target='/dev/base',
|
|
|
|
+ permissions={'mode': '0770',
|
|
|
|
+ 'owner': 1000,
|
|
|
|
+ 'group': 100,
|
|
|
|
+ 'label': 'seclabel'},
|
|
|
|
+ source_devices=[{'path': '/dev/sda'}],
|
|
|
|
+ source_dir=None,
|
|
|
|
+ source_adapter=None,
|
|
|
|
+ source_hosts=None,
|
|
|
|
+ source_auth=None,
|
|
|
|
+ source_name=None,
|
|
|
|
+ source_format=None,
|
|
|
|
+ source_initiator=None,
|
|
|
|
+ transient=True,
|
|
|
|
+ start=False,
|
|
|
|
+ connection='myconnection',
|
|
|
|
+ username='user',
|
|
|
|
+ password='secret')
|
|
|
|
+ mocks['autostart'].assert_called_with('mypool',
|
|
|
|
+ state='on',
|
|
|
|
connection='myconnection',
|
|
|
|
username='user',
|
|
|
|
- password='secret'), ret)
|
|
|
|
- start_mock.assert_called_with('mynet', connection='myconnection', username='user', password='secret')
|
|
|
|
+ password='secret')
|
|
|
|
+ mocks['build'].assert_called_with('mypool',
|
|
|
|
+ connection='myconnection',
|
|
|
|
+ username='user',
|
|
|
|
+ password='secret')
|
|
|
|
|
|
|
|
- with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
- 'virt.network_info': MagicMock(return_value={}),
|
|
|
|
- 'virt.network_define': MagicMock(side_effect=self.mock_libvirt.libvirtError('Some error'))
|
|
|
|
- }):
|
|
|
|
- ret.update({'changes': {}, 'comment': 'Some error', 'result': False})
|
|
|
|
- self.assertDictEqual(virt.network_running('mynet', 'br2', 'bridge'), ret)
|
|
|
|
+ mocks['update'] = MagicMock(return_value=False)
|
|
|
|
+ for mock in mocks:
|
|
|
|
+ mocks[mock].reset_mock()
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.pool_info': MagicMock(return_value={'mypool': {'state': 'stopped', 'autostart': True}}),
|
|
|
|
+ 'virt.pool_update': mocks['update'],
|
|
|
|
+ 'virt.pool_build': mocks['build'],
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {}, 'comment': 'Pool mypool unchanged'})
|
|
|
|
+ self.assertDictEqual(virt.pool_defined('mypool',
|
|
|
|
+ ptype='logical',
|
|
|
|
+ target='/dev/base',
|
|
|
|
+ source={'devices': [{'path': '/dev/sda'}]}), ret)
|
|
|
|
+ mocks['build'].assert_not_called()
|
|
|
|
+
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.pool_info': MagicMock(return_value={}),
|
|
|
|
+ 'virt.pool_define': MagicMock(side_effect=self.mock_libvirt.libvirtError('Some error'))
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {}, 'comment': 'Some error', 'result': False})
|
|
|
|
+ self.assertDictEqual(virt.pool_defined('mypool',
|
|
|
|
+ ptype='logical',
|
|
|
|
+ target='/dev/base',
|
|
|
|
+ source={'devices': [{'path': '/dev/sda'}]}), ret)
|
|
|
|
+
|
|
|
|
+ # Test case with update and autostart change on stopped pool
|
|
|
|
+ for mock in mocks:
|
|
|
|
+ mocks[mock].reset_mock()
|
|
|
|
+ mocks['update'] = MagicMock(return_value=True)
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.pool_info': MagicMock(return_value={'mypool': {'state': 'stopped', 'autostart': True}}),
|
|
|
|
+ 'virt.pool_update': mocks['update'],
|
|
|
|
+ 'virt.pool_set_autostart': mocks['autostart'],
|
|
|
|
+ 'virt.pool_build': mocks['build'],
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'mypool': 'Pool updated, built, autostart flag changed'},
|
|
|
|
+ 'comment': 'Pool mypool updated, built, autostart flag changed',
|
|
|
|
+ 'result': True})
|
|
|
|
+ self.assertDictEqual(virt.pool_defined('mypool',
|
|
|
|
+ ptype='logical',
|
|
|
|
+ target='/dev/base',
|
|
|
|
+ autostart=False,
|
|
|
|
+ permissions={'mode': '0770',
|
|
|
|
+ 'owner': 1000,
|
|
|
|
+ 'group': 100,
|
|
|
|
+ 'label': 'seclabel'},
|
|
|
|
+ source={'devices': [{'path': '/dev/sda'}]}), ret)
|
|
|
|
+ mocks['build'].assert_called_with('mypool', connection=None, username=None, password=None)
|
|
|
|
+ mocks['autostart'].assert_called_with('mypool', state='off',
|
|
|
|
+ connection=None, username=None, password=None)
|
|
|
|
+ mocks['update'].assert_called_with('mypool',
|
|
|
|
+ ptype='logical',
|
|
|
|
+ target='/dev/base',
|
|
|
|
+ permissions={'mode': '0770',
|
|
|
|
+ 'owner': 1000,
|
|
|
|
+ 'group': 100,
|
|
|
|
+ 'label': 'seclabel'},
|
|
|
|
+ source_devices=[{'path': '/dev/sda'}],
|
|
|
|
+ source_dir=None,
|
|
|
|
+ source_adapter=None,
|
|
|
|
+ source_hosts=None,
|
|
|
|
+ source_auth=None,
|
|
|
|
+ source_name=None,
|
|
|
|
+ source_format=None,
|
|
|
|
+ source_initiator=None,
|
|
|
|
+ connection=None,
|
|
|
|
+ username=None,
|
|
|
|
+ password=None)
|
|
|
|
+
|
|
|
|
+ # test case with update and no autostart change on running pool
|
|
|
|
+ for mock in mocks:
|
|
|
|
+ mocks[mock].reset_mock()
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.pool_info': MagicMock(return_value={'mypool': {'state': 'running', 'autostart': False}}),
|
|
|
|
+ 'virt.pool_update': mocks['update'],
|
|
|
|
+ 'virt.pool_build': mocks['build'],
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'mypool': 'Pool updated'},
|
|
|
|
+ 'comment': 'Pool mypool updated',
|
|
|
|
+ 'result': True})
|
|
|
|
+ self.assertDictEqual(virt.pool_defined('mypool',
|
|
|
|
+ ptype='logical',
|
|
|
|
+ target='/dev/base',
|
|
|
|
+ autostart=False,
|
|
|
|
+ permissions={'mode': '0770',
|
|
|
|
+ 'owner': 1000,
|
|
|
|
+ 'group': 100,
|
|
|
|
+ 'label': 'seclabel'},
|
|
|
|
+ source={'devices': [{'path': '/dev/sda'}]}), ret)
|
|
|
|
+ mocks['update'].assert_called_with('mypool',
|
|
|
|
+ ptype='logical',
|
|
|
|
+ target='/dev/base',
|
|
|
|
+ permissions={'mode': '0770',
|
|
|
|
+ 'owner': 1000,
|
|
|
|
+ 'group': 100,
|
|
|
|
+ 'label': 'seclabel'},
|
|
|
|
+ source_devices=[{'path': '/dev/sda'}],
|
|
|
|
+ source_dir=None,
|
|
|
|
+ source_adapter=None,
|
|
|
|
+ source_hosts=None,
|
|
|
|
+ source_auth=None,
|
|
|
|
+ source_name=None,
|
|
|
|
+ source_format=None,
|
|
|
|
+ source_initiator=None,
|
|
|
|
+ connection=None,
|
|
|
|
+ username=None,
|
|
|
|
+ password=None)
|
|
|
|
+
|
|
|
|
+ with patch.dict(virt.__opts__, {'test': True}):
|
|
|
|
+ # test case with test=True and no change
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.pool_info': MagicMock(return_value={'mypool': {'state': 'running', 'autostart': True}}),
|
|
|
|
+ 'virt.pool_update': MagicMock(return_value=False),
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {}, 'comment': 'Pool mypool unchanged',
|
|
|
|
+ 'result': True})
|
|
|
|
+ self.assertDictEqual(virt.pool_defined('mypool',
|
|
|
|
+ ptype='logical',
|
|
|
|
+ target='/dev/base',
|
|
|
|
+ source={'devices': [{'path': '/dev/sda'}]}), ret)
|
|
|
|
+
|
|
|
|
+ # test case with test=True and pool to be defined
|
|
|
|
+ for mock in mocks:
|
|
|
|
+ mocks[mock].reset_mock()
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.pool_info': MagicMock(return_value={}),
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'mypool': 'Pool defined, marked for autostart'},
|
|
|
|
+ 'comment': 'Pool mypool defined, marked for autostart',
|
|
|
|
+ 'result': None})
|
|
|
|
+ self.assertDictEqual(virt.pool_defined('mypool',
|
|
|
|
+ ptype='logical',
|
|
|
|
+ target='/dev/base',
|
|
|
|
+ permissions={'mode': '0770',
|
|
|
|
+ 'owner': 1000,
|
|
|
|
+ 'group': 100,
|
|
|
|
+ 'label': 'seclabel'},
|
|
|
|
+ source={'devices': [{'path': '/dev/sda'}]},
|
|
|
|
+ transient=True,
|
|
|
|
+ autostart=True,
|
|
|
|
+ connection='myconnection',
|
|
|
|
+ username='user',
|
|
|
|
+ password='secret'), ret)
|
|
|
|
|
|
|
|
def test_pool_running(self):
|
|
|
|
'''
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -694,14 +1551,14 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
2020-03-16 16:06:32 +01:00
|
|
|
mocks = {mock: MagicMock(return_value=True) for mock in ['define', 'autostart', 'build', 'start', 'stop']}
|
|
|
|
with patch.dict(virt.__opts__, {'test': False}):
|
|
|
|
with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
- 'virt.pool_info': MagicMock(return_value={}),
|
|
|
|
+ 'virt.pool_info': MagicMock(side_effect=[{}, {'mypool': {'state': 'stopped', 'autostart': True}}]),
|
|
|
|
'virt.pool_define': mocks['define'],
|
|
|
|
'virt.pool_build': mocks['build'],
|
|
|
|
'virt.pool_start': mocks['start'],
|
|
|
|
'virt.pool_set_autostart': mocks['autostart']
|
|
|
|
}):
|
|
|
|
- ret.update({'changes': {'mypool': 'Pool defined, started and marked for autostart'},
|
|
|
|
- 'comment': 'Pool mypool defined, started and marked for autostart'})
|
|
|
|
+ ret.update({'changes': {'mypool': 'Pool defined, marked for autostart, started'},
|
|
|
|
+ 'comment': 'Pool mypool defined, marked for autostart, started'})
|
|
|
|
self.assertDictEqual(virt.pool_running('mypool',
|
|
|
|
ptype='logical',
|
|
|
|
target='/dev/base',
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -754,7 +1611,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
2020-03-16 16:06:32 +01:00
|
|
|
'virt.pool_info': MagicMock(return_value={'mypool': {'state': 'running', 'autostart': True}}),
|
|
|
|
'virt.pool_update': MagicMock(return_value=False),
|
|
|
|
}):
|
|
|
|
- ret.update({'changes': {}, 'comment': 'Pool mypool unchanged and is running'})
|
|
|
|
+ ret.update({'changes': {}, 'comment': 'Pool mypool already running'})
|
|
|
|
self.assertDictEqual(virt.pool_running('mypool',
|
|
|
|
ptype='logical',
|
|
|
|
target='/dev/base',
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -797,8 +1654,8 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
2020-03-16 16:06:32 +01:00
|
|
|
'virt.pool_build': mocks['build'],
|
|
|
|
'virt.pool_start': mocks['start']
|
|
|
|
}):
|
|
|
|
- ret.update({'changes': {'mypool': 'Pool updated, built, autostart flag changed and started'},
|
|
|
|
- 'comment': 'Pool mypool updated, built, autostart flag changed and started',
|
|
|
|
+ ret.update({'changes': {'mypool': 'Pool updated, built, autostart flag changed, started'},
|
|
|
|
+ 'comment': 'Pool mypool updated, built, autostart flag changed, started',
|
|
|
|
'result': True})
|
|
|
|
self.assertDictEqual(virt.pool_running('mypool',
|
|
|
|
ptype='logical',
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -842,8 +1699,8 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
2020-03-16 16:06:32 +01:00
|
|
|
'virt.pool_start': mocks['start'],
|
|
|
|
'virt.pool_stop': mocks['stop']
|
|
|
|
}):
|
|
|
|
- ret.update({'changes': {'mypool': 'Pool updated, built and restarted'},
|
|
|
|
- 'comment': 'Pool mypool updated, built and restarted',
|
|
|
|
+ ret.update({'changes': {'mypool': 'Pool updated, built, restarted'},
|
|
|
|
+ 'comment': 'Pool mypool updated, built, restarted',
|
|
|
|
'result': True})
|
|
|
|
self.assertDictEqual(virt.pool_running('mypool',
|
|
|
|
ptype='logical',
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -882,7 +1739,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
2020-03-16 16:06:32 +01:00
|
|
|
'virt.pool_info': MagicMock(return_value={'mypool': {'state': 'running', 'autostart': True}}),
|
|
|
|
'virt.pool_update': MagicMock(return_value=False),
|
|
|
|
}):
|
|
|
|
- ret.update({'changes': {}, 'comment': 'Pool mypool unchanged and is running',
|
|
|
|
+ ret.update({'changes': {}, 'comment': 'Pool mypool already running',
|
|
|
|
'result': True})
|
|
|
|
self.assertDictEqual(virt.pool_running('mypool',
|
|
|
|
ptype='logical',
|
2020-04-07 14:14:01 +02:00
|
|
|
@@ -905,6 +1762,29 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
2020-03-16 16:06:32 +01:00
|
|
|
target='/dev/base',
|
|
|
|
source={'devices': [{'path': '/dev/sda'}]}), ret)
|
|
|
|
|
|
|
|
+ # test case with test=True and pool to be defined
|
|
|
|
+ for mock in mocks:
|
|
|
|
+ mocks[mock].reset_mock()
|
|
|
|
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
|
|
|
|
+ 'virt.pool_info': MagicMock(return_value={}),
|
|
|
|
+ }):
|
|
|
|
+ ret.update({'changes': {'mypool': 'Pool defined, marked for autostart, started'},
|
|
|
|
+ 'comment': 'Pool mypool defined, marked for autostart, started',
|
|
|
|
+ 'result': None})
|
|
|
|
+ self.assertDictEqual(virt.pool_running('mypool',
|
|
|
|
+ ptype='logical',
|
|
|
|
+ target='/dev/base',
|
|
|
|
+ permissions={'mode': '0770',
|
|
|
|
+ 'owner': 1000,
|
|
|
|
+ 'group': 100,
|
|
|
|
+ 'label': 'seclabel'},
|
|
|
|
+ source={'devices': [{'path': '/dev/sda'}]},
|
|
|
|
+ transient=True,
|
|
|
|
+ autostart=True,
|
|
|
|
+ connection='myconnection',
|
|
|
|
+ username='user',
|
|
|
|
+ password='secret'), ret)
|
|
|
|
+
|
|
|
|
def test_pool_deleted(self):
|
|
|
|
'''
|
|
|
|
Test the pool_deleted state
|
|
|
|
--
|
|
|
|
2.16.4
|
|
|
|
|
|
|
|
|