File: //usr/lib/python2.7/site-packages/salt/states/virt.py
# -*- coding: utf-8 -*-
'''
Manage virt
===========
For the key certificate this state uses the external pillar in the master to call
for the generation and signing of certificates for systems running libvirt:
.. code-block:: yaml
libvirt_keys:
virt.keys
'''
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals
import fnmatch
import os
try:
import libvirt # pylint: disable=import-error
HAS_LIBVIRT = True
except ImportError:
HAS_LIBVIRT = False
# Import Salt libs
import salt.utils.args
import salt.utils.files
import salt.utils.stringutils
import salt.utils.versions
from salt.exceptions import CommandExecutionError
# Import 3rd-party libs
from salt.ext import six
__virtualname__ = 'virt'
def __virtual__():
'''
Only if virt module is available.
:return:
'''
if 'virt.node_info' in __salt__:
return __virtualname__
return False
def keys(name, basepath='/etc/pki', **kwargs):
'''
Manage libvirt keys.
name
The name variable used to track the execution
basepath
Defaults to ``/etc/pki``, this is the root location used for libvirt
keys on the hypervisor
The following parameters are optional:
country
The country that the certificate should use. Defaults to US.
.. versionadded:: 2018.3.0
state
The state that the certificate should use. Defaults to Utah.
.. versionadded:: 2018.3.0
locality
The locality that the certificate should use.
Defaults to Salt Lake City.
.. versionadded:: 2018.3.0
organization
The organization that the certificate should use.
Defaults to Salted.
.. versionadded:: 2018.3.0
expiration_days
The number of days that the certificate should be valid for.
Defaults to 365 days (1 year)
.. versionadded:: 2018.3.0
'''
ret = {'name': name, 'changes': {}, 'result': True, 'comment': ''}
# Grab all kwargs to make them available as pillar values
# rename them to something hopefully unique to avoid
# overriding anything existing
pillar_kwargs = {}
for key, value in six.iteritems(kwargs):
pillar_kwargs['ext_pillar_virt.{0}'.format(key)] = value
pillar = __salt__['pillar.ext']({'libvirt': '_'}, pillar_kwargs)
paths = {
'serverkey': os.path.join(basepath, 'libvirt',
'private', 'serverkey.pem'),
'servercert': os.path.join(basepath, 'libvirt',
'servercert.pem'),
'clientkey': os.path.join(basepath, 'libvirt',
'private', 'clientkey.pem'),
'clientcert': os.path.join(basepath, 'libvirt',
'clientcert.pem'),
'cacert': os.path.join(basepath, 'CA', 'cacert.pem')
}
for key in paths:
p_key = 'libvirt.{0}.pem'.format(key)
if p_key not in pillar:
continue
if not os.path.exists(os.path.dirname(paths[key])):
os.makedirs(os.path.dirname(paths[key]))
if os.path.isfile(paths[key]):
with salt.utils.files.fopen(paths[key], 'r') as fp_:
if salt.utils.stringutils.to_unicode(fp_.read()) != pillar[p_key]:
ret['changes'][key] = 'update'
else:
ret['changes'][key] = 'new'
if not ret['changes']:
ret['comment'] = 'All keys are correct'
elif __opts__['test']:
ret['result'] = None
ret['comment'] = 'Libvirt keys are set to be updated'
ret['changes'] = {}
else:
for key in ret['changes']:
with salt.utils.files.fopen(paths[key], 'w+') as fp_:
fp_.write(
salt.utils.stringutils.to_str(
pillar['libvirt.{0}.pem'.format(key)]
)
)
ret['comment'] = 'Updated libvirt certs and keys'
return ret
def _virt_call(domain, function, section, comment, state=None,
connection=None, username=None, password=None, **kwargs):
'''
Helper to call the virt functions. Wildcards supported.
:param domain: the domain to apply the function on. Can contain wildcards.
:param function: virt function to call
:param section: key for the changed domains in the return changes dictionary
:param comment: comment to return
:param state: the expected final state of the VM. If None the VM state won't be checked.
:return: the salt state return
'''
ret = {'name': domain, 'changes': {}, 'result': True, 'comment': ''}
targeted_domains = fnmatch.filter(__salt__['virt.list_domains'](), domain)
changed_domains = list()
ignored_domains = list()
noaction_domains = list()
for targeted_domain in targeted_domains:
try:
action_needed = True
# If a state has been provided, use it to see if we have something to do
if state is not None:
domain_state = __salt__['virt.vm_state'](targeted_domain)
action_needed = domain_state.get(targeted_domain) != state
if action_needed:
response = __salt__['virt.{0}'.format(function)](targeted_domain,
connection=connection,
username=username,
password=password,
**kwargs)
if isinstance(response, dict):
response = response['name']
changed_domains.append({'domain': targeted_domain, function: response})
else:
noaction_domains.append(targeted_domain)
except libvirt.libvirtError as err:
ignored_domains.append({'domain': targeted_domain, 'issue': six.text_type(err)})
if not changed_domains:
ret['result'] = not ignored_domains and bool(targeted_domains)
ret['comment'] = 'No changes had happened'
if ignored_domains:
ret['changes'] = {'ignored': ignored_domains}
else:
ret['changes'] = {section: changed_domains}
ret['comment'] = comment
return ret
def stopped(name, connection=None, username=None, password=None):
'''
Stops a VM by shutting it down nicely.
.. versionadded:: 2016.3.0
:param connection: libvirt connection URI, overriding defaults
.. versionadded:: 2019.2.0
:param username: username to connect with, overriding defaults
.. versionadded:: 2019.2.0
:param password: password to connect with, overriding defaults
.. versionadded:: 2019.2.0
.. code-block:: yaml
domain_name:
virt.stopped
'''
return _virt_call(name, 'shutdown', 'stopped', 'Machine has been shut down', state='shutdown',
connection=connection, username=username, password=password)
def powered_off(name, connection=None, username=None, password=None):
'''
Stops a VM by power off.
.. versionadded:: 2016.3.0
:param connection: libvirt connection URI, overriding defaults
.. versionadded:: 2019.2.0
:param username: username to connect with, overriding defaults
.. versionadded:: 2019.2.0
:param password: password to connect with, overriding defaults
.. versionadded:: 2019.2.0
.. code-block:: yaml
domain_name:
virt.stopped
'''
return _virt_call(name, 'stop', 'unpowered', 'Machine has been powered off', state='shutdown',
connection=connection, username=username, password=password)
def running(name,
cpu=None,
mem=None,
image=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,
update=False,
connection=None,
username=None,
password=None,
os_type=None,
arch=None,
boot=None):
'''
Starts an existing guest, or defines and starts a new VM with specified arguments.
.. versionadded:: 2016.3.0
: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 image: disk image to use for the first disk of the new VM
.. deprecated:: 2019.2.0
: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.
.. versionadded:: 2019.2.0
:param disk_profile:
Name of the disk profile to use for the new virtual machine
.. versionadded:: 2019.2.0
: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.
.. versionadded:: 2019.2.0
:param nic_profile:
Name of the network interfaces profile to use for the new virtual machine
.. versionadded:: 2019.2.0
: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.
.. versionadded:: 2019.2.0
:param graphics:
Graphics device to create for the new virtual machine.
See :ref:`init-graphics-def` for more details on this dictionary
.. versionadded:: 2019.2.0
:param saltenv:
Fileserver environment (Default: ``'base'``).
See :mod:`cp module for more details <salt.modules.cp>`
.. versionadded:: 2019.2.0
:param seed: ``True`` to seed the disk image. Only used when the ``image`` parameter is provided.
(Default: ``True``)
.. versionadded:: 2019.2.0
:param install: install salt minion if absent (Default: ``True``)
.. versionadded:: 2019.2.0
:param pub_key: public key to seed with (Default: ``None``)
.. versionadded:: 2019.2.0
:param priv_key: public key to seed with (Default: ``None``)
.. versionadded:: 2019.2.0
: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``)
.. versionadded:: 2019.2.0
:param connection: libvirt connection URI, overriding defaults
.. versionadded:: 2019.2.0
:param username: username to connect with, overriding defaults
.. versionadded:: 2019.2.0
:param password: password to connect with, overriding defaults
.. versionadded:: 2019.2.0
: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.
.. versionadded:: 3000
: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.
.. versionadded:: 3000
: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/'
}
.. versionadded:: 3000
.. rubric:: Example States
Make sure an already-defined virtual machine called ``domain_name`` is running:
.. code-block:: yaml
domain_name:
virt.running
Do the same, but define the virtual machine if needed:
.. code-block:: yaml
domain_name:
virt.running:
- 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,
'comment': '{0} is running'.format(name)
}
try:
try:
domain_state = __salt__['virt.vm_state'](name)
if domain_state.get(name) != 'running':
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
return ret
def snapshot(name, suffix=None, connection=None, username=None, password=None):
'''
Takes a snapshot of a particular VM or by a UNIX-style wildcard.
.. versionadded:: 2016.3.0
:param connection: libvirt connection URI, overriding defaults
.. versionadded:: 2019.2.0
:param username: username to connect with, overriding defaults
.. versionadded:: 2019.2.0
:param password: password to connect with, overriding defaults
.. versionadded:: 2019.2.0
.. code-block:: yaml
domain_name:
virt.snapshot:
- suffix: periodic
domain*:
virt.snapshot:
- suffix: periodic
'''
return _virt_call(name, 'snapshot', 'saved', 'Snapshot has been taken', suffix=suffix,
connection=connection, username=username, password=password)
# Deprecated states
def rebooted(name, connection=None, username=None, password=None):
'''
Reboots VMs
.. versionadded:: 2016.3.0
:param name:
:param connection: libvirt connection URI, overriding defaults
.. versionadded:: 2019.2.0
:param username: username to connect with, overriding defaults
.. versionadded:: 2019.2.0
:param password: password to connect with, overriding defaults
.. versionadded:: 2019.2.0
'''
return _virt_call(name, 'reboot', 'rebooted', "Machine has been rebooted",
connection=connection, username=username, password=password)
def unpowered(name):
'''
.. deprecated:: 2016.3.0
Use :py:func:`~salt.modules.virt.powered_off` instead.
Stops a VM by power off.
.. versionadded:: 2016.3.0
.. code-block:: yaml
domain_name:
virt.stopped
'''
return _virt_call(name, 'stop', 'unpowered', 'Machine has been powered off')
def saved(name, suffix=None):
'''
.. deprecated:: 2016.3.0
Use :py:func:`~salt.modules.virt.snapshot` instead.
Takes a snapshot of a particular VM or by a UNIX-style wildcard.
.. versionadded:: 2016.3.0
.. code-block:: yaml
domain_name:
virt.saved:
- suffix: periodic
domain*:
virt.saved:
- suffix: periodic
'''
return _virt_call(name, 'snapshot', 'saved', 'Snapshots has been taken', suffix=suffix)
def reverted(name, snapshot=None, cleanup=False): # pylint: disable=redefined-outer-name
'''
.. deprecated:: 2016.3.0
Reverts to the particular snapshot.
.. versionadded:: 2016.3.0
.. code-block:: yaml
domain_name:
virt.reverted:
- cleanup: True
domain_name_1:
virt.reverted:
- snapshot: snapshot_name
- cleanup: False
'''
ret = {'name': name, 'changes': {}, 'result': False, 'comment': ''}
try:
domains = fnmatch.filter(__salt__['virt.list_domains'](), name)
if not domains:
ret['comment'] = 'No domains found for criteria "{0}"'.format(name)
else:
ignored_domains = list()
if len(domains) > 1:
ret['changes'] = {'reverted': list()}
for domain in domains:
result = {}
try:
result = __salt__['virt.revert_snapshot'](domain, snapshot=snapshot, cleanup=cleanup)
result = {'domain': domain, 'current': result['reverted'], 'deleted': result['deleted']}
except CommandExecutionError as err:
if len(domains) > 1:
ignored_domains.append({'domain': domain, 'issue': six.text_type(err)})
if len(domains) > 1:
if result:
ret['changes']['reverted'].append(result)
else:
ret['changes'] = result
break
ret['result'] = len(domains) != len(ignored_domains)
if ret['result']:
ret['comment'] = 'Domain{0} has been reverted'.format(len(domains) > 1 and "s" or "")
if ignored_domains:
ret['changes']['ignored'] = ignored_domains
if not ret['changes']['reverted']:
ret['changes'].pop('reverted')
except libvirt.libvirtError as err:
ret['comment'] = six.text_type(err)
except CommandExecutionError as err:
ret['comment'] = six.text_type(err)
return ret
def network_running(name,
bridge,
forward,
vport=None,
tag=None,
ipv4_config=None,
ipv6_config=None,
autostart=True,
connection=None,
username=None,
password=None):
'''
Defines and starts 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).
.. versionadded:: 3000
: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).
.. versionadded:: 3000
:param autostart: Network autostart (default ``'True'``)
:param connection: libvirt connection URI, overriding defaults
.. versionadded:: 2019.2.0
:param username: username to connect with, overriding defaults
.. versionadded:: 2019.2.0
:param password: password to connect with, overriding defaults
.. versionadded:: 2019.2.0
.. code-block:: yaml
domain_name:
virt.network_define
.. code-block:: yaml
network_name:
virt.network_define:
- bridge: main
- forward: bridge
- vport: openvswitch
- tag: 180
- autostart: True
.. code-block:: yaml
network_name:
virt.network_define:
- 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,
'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)
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()
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_define
.. code-block:: yaml
pool_name:
virt.pool_define:
- 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 = {'name': name,
'changes': {},
'result': True if not __opts__['test'] else None,
'comment': ''
}
try:
info = __salt__['virt.pool_info'](name, connection=connection, username=username, password=password)
needs_autostart = False
if info:
needs_autostart = info[name]['autostart'] and not autostart or not info[name]['autostart'] and autostart
# Update can happen for both running and stopped pools
needs_update = __salt__['virt.pool_update'](name,
ptype=ptype,
target=target,
permissions=permissions,
source_devices=(source or {}).get('devices'),
source_dir=(source or {}).get('dir'),
source_initiator=(source or {}).get('initiator'),
source_adapter=(source or {}).get('adapter'),
source_hosts=(source or {}).get('hosts'),
source_auth=(source or {}).get('auth'),
source_name=(source or {}).get('name'),
source_format=(source or {}).get('format'),
test=True,
connection=connection,
username=username,
password=password)
if needs_update:
if not __opts__['test']:
__salt__['virt.pool_update'](name,
ptype=ptype,
target=target,
permissions=permissions,
source_devices=(source or {}).get('devices'),
source_dir=(source or {}).get('dir'),
source_initiator=(source or {}).get('initiator'),
source_adapter=(source or {}).get('adapter'),
source_hosts=(source or {}).get('hosts'),
source_auth=(source or {}).get('auth'),
source_name=(source or {}).get('name'),
source_format=(source or {}).get('format'),
connection=connection,
username=username,
password=password)
action = "started"
if info[name]['state'] == 'running':
action = "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)
__salt__['virt.pool_start'](name, connection=connection, username=username, password=password)
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)
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)
else:
needs_autostart = autostart
if not __opts__['test']:
__salt__['virt.pool_define'](name,
ptype=ptype,
target=target,
permissions=permissions,
source_devices=(source or {}).get('devices'),
source_dir=(source or {}).get('dir'),
source_initiator=(source or {}).get('initiator'),
source_adapter=(source or {}).get('adapter'),
source_hosts=(source or {}).get('hosts'),
source_auth=(source or {}).get('auth'),
source_name=(source or {}).get('name'),
source_format=(source or {}).get('format'),
transient=transient,
start=False,
connection=connection,
username=username,
password=password)
__salt__['virt.pool_build'](name,
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)
else:
ret['changes'][name] = 'Pool defined and started'
ret['comment'] = 'Pool {0} defined and started'.format(name)
if needs_autostart:
if not __opts__['test']:
__salt__['virt.pool_set_autostart'](name,
state='on' if autostart else 'off',
connection=connection,
username=username,
password=password)
except libvirt.libvirtError as err:
ret['comment'] = err.get_error_message()
ret['result'] = False
return ret
def pool_deleted(name,
purge=False,
connection=None,
username=None,
password=None):
'''
Deletes a virtual storage pool.
:param name: the name of the pool to delete.
:param purge:
if ``True``, the volumes contained in the pool will be deleted as well as the pool itself.
Note that these will be lost for ever. If ``False`` the pool will simply be undefined.
(Default: ``False``)
:param connection: libvirt connection URI, overriding defaults
:param username: username to connect with, overriding defaults
:param password: password to connect with, overriding defaults
In order to be purged a storage pool needs to be running to get the list of volumes to delete.
Some libvirt storage drivers may not implement deleting, those actions are implemented on a
best effort idea. In any case check the result's comment property to see if any of the action
was unsupported.
.. code-block::yaml
pool_name:
uyuni_virt.pool_deleted:
- purge: True
.. versionadded:: 3000
'''
ret = {'name': name, 'changes': {}, 'result': True, 'comment': ''}
try:
info = __salt__['virt.pool_info'](name, connection=connection, username=username, password=password)
if info:
ret['changes']['stopped'] = False
ret['changes']['deleted'] = False
ret['changes']['undefined'] = False
ret['changes']['deleted_volumes'] = []
unsupported = []
if info[name]['state'] == 'running':
if purge:
unsupported_volume_delete = ['iscsi', 'iscsi-direct', 'mpath', 'scsi']
if info[name]['type'] not in unsupported_volume_delete:
__salt__['virt.pool_refresh'](name,
connection=connection,
username=username,
password=password)
volumes = __salt__['virt.pool_list_volumes'](name,
connection=connection,
username=username,
password=password)
for volume in volumes:
# Not supported for iSCSI and SCSI drivers
deleted = __opts__['test']
if not __opts__['test']:
deleted = __salt__['virt.volume_delete'](name,
volume,
connection=connection,
username=username,
password=password)
if deleted:
ret['changes']['deleted_volumes'].append(volume)
else:
unsupported.append('deleting volume')
if not __opts__['test']:
ret['changes']['stopped'] = __salt__['virt.pool_stop'](name,
connection=connection,
username=username,
password=password)
else:
ret['changes']['stopped'] = True
if purge:
supported_pool_delete = ['dir', 'fs', 'netfs', 'logical', 'vstorage', 'zfs']
if info[name]['type'] in supported_pool_delete:
if not __opts__['test']:
ret['changes']['deleted'] = __salt__['virt.pool_delete'](name,
connection=connection,
username=username,
password=password)
else:
ret['changes']['deleted'] = True
else:
unsupported.append('deleting pool')
if not __opts__['test']:
ret['changes']['undefined'] = __salt__['virt.pool_undefine'](name,
connection=connection,
username=username,
password=password)
else:
ret['changes']['undefined'] = True
ret['result'] = None
if unsupported:
ret['comment'] = 'Unsupported actions for pool of type "{0}": {1}'.format(info[name]['type'],
', '.join(unsupported))
else:
ret['comment'] = 'Storage pool could not be found: {0}'.format(name)
except libvirt.libvirtError as err:
ret['comment'] = 'Failed deleting pool: {0}'.format(err.get_error_message())
ret['result'] = False
return ret