Salt Virt cleanup

This commit is contained in:
Joseph Hall 2016-01-22 10:53:23 -07:00
parent 05d05263ab
commit 6413c11f29
4 changed files with 260 additions and 130 deletions

View file

@ -10,10 +10,13 @@ from __future__ import absolute_import
import os
import tempfile
import hashlib
import logging
# Import Salt libs
import salt.utils
log = logging.getLogger(__name__)
def __virtual__():
'''
@ -35,26 +38,28 @@ def mount(location, access='rw'):
salt '*' guest.mount /srv/images/fedora.qcow
'''
root = os.path.join(
tempfile.gettempdir(),
'guest',
location.lstrip(os.sep).replace('/', '.')
)
tempfile.gettempdir(),
'guest',
location.lstrip(os.sep).replace('/', '.')
)
log.debug('Using root {0}'.format(root))
if not os.path.isdir(root):
try:
os.makedirs(root)
except OSError:
# somehow the directory already exists
# Somehow the path already exists
pass
while True:
if os.listdir(root):
# Stuf is in there, don't use it
# Stuff is in there, don't use it
hash_type = getattr(hashlib, __opts__.get('hash_type', 'md5'))
rand = hash_type(os.urandom(32)).hexdigest()
root = os.path.join(
tempfile.gettempdir(),
'guest',
location.lstrip(os.sep).replace('/', '.') + rand
)
)
log.debug('Establishing new root as {0}'.format(root))
else:
break
cmd = 'guestmount -i -a {0} --{1} {2}'.format(location, access, root)

View file

@ -86,7 +86,7 @@ def _umount(mpt, ftype):
def apply_(path, id_=None, config=None, approve_key=True, install=True,
prep_install=False):
prep_install=False, pub_key=None, priv_key=None):
'''
Seed a location (disk image, directory, or block device) with the
minion config, approve the minion's key, and/or install salt-minion.
@ -126,18 +126,27 @@ def apply_(path, id_=None, config=None, approve_key=True, install=True,
return '{0} does not exist'.format(path)
ftype = stats['type']
path = stats['target']
log.debug('Mounting {0} at {1}'.format(ftype, path))
try:
os.makedirs(path)
except OSError:
# The directory already exists
pass
mpt = _mount(path, ftype)
if not mpt:
return '{0} could not be mounted'.format(path)
tmp = os.path.join(mpt, 'tmp')
log.debug('Attempting to create directory {0}'.format(tmp))
try:
os.makedirs(tmp)
except OSError:
if not os.path.isdir(tmp):
raise
cfg_files = mkconfig(config, tmp=tmp, id_=id_, approve_key=approve_key)
cfg_files = mkconfig(config, tmp=tmp, id_=id_, approve_key=approve_key,
pub_key=pub_key, priv_key=priv_key)
if _check_install(mpt):
# salt-minion is already installed, just move the config and keys
@ -157,8 +166,7 @@ def apply_(path, id_=None, config=None, approve_key=True, install=True,
os.rename(cfg_files['config'], os.path.join(mpt, 'etc/salt/minion'))
res = True
elif install:
log.info('attempting to install salt-minion to '
'{0}'.format(mpt))
log.info('Attempting to install salt-minion to {0}'.format(mpt))
res = _install(mpt)
elif prep_install:
log.error('The prep_install option is no longer supported. Please use '
@ -214,12 +222,16 @@ def mkconfig(config=None,
privkeyfn = os.path.join(tmp, 'minion.pem')
preseeded = pub_key and priv_key
if preseeded:
log.debug('Writing minion.pub to {0}'.format(pubkeyfn))
log.debug('Writing minion.pem to {0}'.format(privkeyfn))
with salt.utils.fopen(pubkeyfn, 'w') as fic:
fic.write(_file_or_content(pub_key))
with salt.utils.fopen(privkeyfn, 'w') as fic:
fic.write(_file_or_content(priv_key))
os.chmod(pubkeyfn, 0o600)
os.chmod(privkeyfn, 0o600)
with salt.utils.fopen(pubkeyfn, 'w') as fic:
fic.write(_file_or_content(pub_key))
else:
salt.crypt.gen_keys(tmp, 'minion', 2048)
if approve_key and not preseeded:
@ -236,7 +248,6 @@ def _install(mpt):
install it.
Return True if install is successful or already installed.
'''
_check_resolv(mpt)
boot_, tmppath = (prep_bootstrap(mpt)
or salt.syspaths.BOOTSTRAP)

View file

@ -27,6 +27,7 @@ from salt.ext.six.moves import StringIO as _StringIO # pylint: disable=import-e
from xml.dom import minidom
try:
import libvirt # pylint: disable=import-error
from libvirt import libvirtError
HAS_LIBVIRT = True
except ImportError:
HAS_LIBVIRT = False
@ -139,7 +140,7 @@ def __get_conn():
__esxi_auth(),
0]],
'qemu': [libvirt.open, [conn_str]],
}
}
hypervisor = __salt__['config.get']('libvirt:hypervisor', 'qemu')
@ -214,7 +215,7 @@ def _gen_xml(name,
hypervisor,
**kwargs):
'''
Generate the XML string to define a libvirt vm
Generate the XML string to define a libvirt VM
'''
hypervisor = 'vmware' if hypervisor == 'esxi' else hypervisor
mem = mem * 1024 # MB
@ -501,9 +502,9 @@ def _nic_profile(profile_name, hypervisor, **kwargs):
attributes[key] = value
def _assign_mac(attributes):
dmac = '{0}_mac'.format(attributes['name'])
if dmac in kwargs:
dmac = kwargs[dmac]
dmac = kwargs.get('dmac', None)
if dmac is not None:
log.debug('DMAC address is {0}'.format(dmac))
if salt.utils.validate.net.mac(dmac):
attributes['mac'] = dmac
else:
@ -530,6 +531,11 @@ def init(name,
start=True, # pylint: disable=redefined-outer-name
disk='default',
saltenv='base',
seed=True,
install=True,
pub_key=None,
priv_key=None,
seed_cmd='seed.apply',
**kwargs):
'''
Initialize a new vm
@ -542,17 +548,21 @@ def init(name,
salt 'hypervisor' virt.init vm_name 4 512 nic=profile disk=profile
'''
hypervisor = __salt__['config.get']('libvirt:hypervisor', hypervisor)
log.debug('Using hyperisor {0}'.format(hypervisor))
nicp = _nic_profile(nic, hypervisor, **kwargs)
log.debug('NIC profile is {0}'.format(nicp))
diskp = None
seedable = False
if image: # with disk template image
log.debug('Image {0} will be used'.format(image))
# if image was used, assume only one disk, i.e. the
# 'default' disk profile
# TODO: make it possible to use disk profiles and use the
# template image as the system disk
diskp = _disk_profile('default', hypervisor, **kwargs)
log.debug('Disk profile is {0}'.format(diskp))
# When using a disk profile extract the sole dict key of the first
# array element as the filename for disk
@ -562,9 +572,10 @@ def init(name,
if hypervisor in ['esxi', 'vmware']:
# TODO: we should be copying the image file onto the ESX host
raise SaltInvocationError('virt.init does not support image '
'template template in conjunction '
'with esxi hypervisor')
raise SaltInvocationError(
'virt.init does not support image template template in '
'conjunction with esxi hypervisor'
)
elif hypervisor in ['qemu', 'kvm']:
img_dir = __salt__['config.option']('virt.images')
img_dest = os.path.join(
@ -574,55 +585,71 @@ def init(name,
)
img_dir = os.path.dirname(img_dest)
sfn = __salt__['cp.cache_file'](image, saltenv)
if not os.path.isdir(img_dir):
os.makedirs(img_dir)
log.debug('Image directory is {0}'.format(img_dir))
try:
os.makedirs(img_dir)
except OSError:
pass
try:
log.debug('Copying {0} to {1}'.format(sfn, img_dest))
salt.utils.files.copyfile(sfn, img_dest)
mask = os.umask(0)
os.umask(mask)
# Apply umask and remove exec bit
mode = (0o0777 ^ mask) & 0o0666
os.chmod(img_dest, mode)
except (IOError, OSError) as e:
raise CommandExecutionError('problem copying image. {0} - {1}'.format(image, e))
seedable = True
else:
log.error('unsupported hypervisor when handling disk image')
log.error('Unsupported hypervisor when handling disk image')
else:
# no disk template image specified, create disks based on disk profile
diskp = _disk_profile(disk, hypervisor, **kwargs)
log.debug('No image specified, disk profile will be used: {0}'.format(diskp))
if hypervisor in ['qemu', 'kvm']:
# TODO: we should be creating disks in the local filesystem with
# qemu-img
raise SaltInvocationError('virt.init does not support disk '
'profiles in conjunction with '
'qemu/kvm at this time, use image '
'template instead')
raise SaltInvocationError(
'virt.init does not support disk profiles in conjunction with '
'qemu/kvm at this time, use image template instead'
)
else:
# assume libvirt manages disks for us
for disk in diskp:
for disk_name, args in six.iteritems(disk):
xml = _gen_vol_xml(name,
disk_name,
args['size'],
hypervisor)
log.debug('Generating libvirt XML for {0}'.format(disk))
xml = _gen_vol_xml(
name,
disk_name,
args['size'],
hypervisor,
)
define_vol_xml_str(xml)
log.debug('Generating VM XML')
xml = _gen_xml(name, cpu, mem, diskp, nicp, hypervisor, **kwargs)
define_xml_str(xml)
try:
define_xml_str(xml)
except libvirtError:
# This domain already exists
pass
if kwargs.get('seed') and seedable:
install = kwargs.get('install', True)
seed_cmd = kwargs.get('seed_cmd', 'seed.apply')
__salt__[seed_cmd](img_dest,
id_=name,
config=kwargs.get('config'),
install=install)
if seed and seedable:
log.debug('Seed command is {0}'.format(seed_cmd))
__salt__[seed_cmd](
img_dest,
id_=name,
config=kwargs.get('config'),
install=install,
pub_key=pub_key,
priv_key=priv_key,
)
if start:
log.debug('Creating {0}'.format(name))
create(name)
return True

View file

@ -5,11 +5,13 @@ Control virtual machines via Salt
# Import python libs
from __future__ import absolute_import, print_function
import os.path
import logging
# Import Salt libs
import salt.client
import salt.utils.virt
import salt.utils.cloud
import salt.key
from salt.exceptions import SaltClientError
@ -19,14 +21,13 @@ import salt.ext.six as six
log = logging.getLogger(__name__)
def _determine_hyper(data, omit=''):
def _determine_host(data, omit=''):
'''
Determine what the most resource free hypervisor is based on the given
data
Determine what the most resource free host is based on the given data
'''
# This is just checking for the hyper with the most free ram, this needs
# This is just checking for the host with the most free ram, this needs
# to be much more complicated.
hyper = ''
host = ''
bestmem = 0
for hv_, comps in six.iteritems(data):
if hv_ == omit:
@ -35,13 +36,13 @@ def _determine_hyper(data, omit=''):
continue
if comps.get('freemem', 0) > bestmem:
bestmem = comps['freemem']
hyper = hv_
return hyper
host = hv_
return host
def _find_vm(name, data, quiet=False):
'''
Scan the query data for the named vm
Scan the query data for the named VM
'''
for hv_ in data:
# Check if data is a dict, and not '"virt.full_info" is not available.'
@ -55,12 +56,20 @@ def _find_vm(name, data, quiet=False):
return {}
def query(hyper=None, quiet=False):
def query(host=None, quiet=False, hyper=None):
'''
Query the virtual machines. When called without options all hypervisors
are detected and a full query is returned. A single hypervisor can be
passed in to specify an individual hypervisor to query.
Query the virtual machines. When called without options all hosts
are detected and a full query is returned. A single host can be
passed in to specify an individual host to query.
'''
if hyper is not None:
salt.utils.warn_until(
'Carbon',
'Please use "host" instead of "hyper". The "hyper" argument will '
'be removed in the Carbon release of Salt'
)
host = hyper
if quiet:
log.warn('\'quiet\' is deprecated. Please migrate to --quiet')
ret = {}
@ -74,8 +83,8 @@ def query(hyper=None, quiet=False):
continue
chunk = {}
id_ = next(info.iterkeys())
if hyper:
if hyper != id_:
if host:
if host != id_:
continue
if not isinstance(info[id_], dict):
continue
@ -92,13 +101,21 @@ def query(hyper=None, quiet=False):
return ret
def list(hyper=None, quiet=False): # pylint: disable=redefined-builtin
def list(host=None, quiet=False, hyper=None): # pylint: disable=redefined-builtin
'''
List the virtual machines on each hyper, this is a simplified query,
showing only the virtual machine names belonging to each hypervisor.
A single hypervisor can be passed in to specify an individual hypervisor
List the virtual machines on each host, this is a simplified query,
showing only the virtual machine names belonging to each host.
A single host can be passed in to specify an individual host
to list.
'''
if hyper is not None:
salt.utils.warn_until(
'Carbon',
'Please use "host" instead of "hyper". The "hyper" argument will '
'be removed in the Carbon release of Salt'
)
host = hyper
if quiet:
log.warn('\'quiet\' is deprecated. Please migrate to --quiet')
ret = {}
@ -111,8 +128,8 @@ def list(hyper=None, quiet=False): # pylint: disable=redefined-builtin
continue
chunk = {}
id_ = next(six.iterkeys(info))
if hyper:
if hyper != id_:
if host:
if host != id_:
continue
if not isinstance(info[id_], dict):
continue
@ -134,22 +151,37 @@ def list(hyper=None, quiet=False): # pylint: disable=redefined-builtin
return ret
def next_host():
'''
Return the host to use for the next autodeployed VM. This queries
the available host and executes some math the determine the most
"available" next host.
'''
host = _determine_host(query(quiet=True))
print(host)
return host
def next_hyper():
'''
Return the hypervisor to use for the next autodeployed vm. This queries
the available hypervisors and executes some math the determine the most
"available" next hypervisor.
Return the host to use for the next autodeployed VM. This queries
the available host and executes some math the determine the most
"available" next host.
'''
hyper = _determine_hyper(query(quiet=True))
print(hyper)
return hyper
if hyper is not None:
salt.utils.warn_until(
'Carbon',
'Please use "host" instead of "hyper". The "hyper" argument will '
'be removed in the Carbon release of Salt'
)
return next_host()
def hyper_info(hyper=None):
def host_info(host=None):
'''
Return information about the hypervisors connected to this master
Return information about the host connected to this master
'''
data = query(hyper, quiet=True)
data = query(host, quiet=True)
for id_ in data:
if 'vm_info' in data[id_]:
data[id_].pop('vm_info')
@ -157,15 +189,33 @@ def hyper_info(hyper=None):
return data
def hyper_info(hyper=None):
'''
Return information about the host connected to this master
'''
if hyper is not None:
salt.utils.warn_until(
'Carbon',
'Please use "host" instead of "hyper". The "hyper" argument will '
'be removed in the Carbon release of Salt'
)
return host_info(hyper)
def init(
name,
cpu,
mem,
image,
hyper=None,
hypervisor='kvm',
host=None,
seed=True,
nic='default',
install=True):
install=True,
start=True,
disk='default',
saltenv='base'):
'''
This routine is used to create a new virtual machine. This routines takes
a number of options to determine what the newly created virtual machine
@ -186,58 +236,94 @@ def init(
The network location of the virtual machine image, commonly a location
on the salt fileserver, but http, https and ftp can also be used.
hyper
The hypervisor to use for the new virtual machine, if this is omitted
Salt will automatically detect what hypervisor to use.
hypervisor
The hypervisor to use for the new virtual machine. Default is 'kvm'.
host
The host to use for the new virtual machine, if this is omitted
Salt will automatically detect what host to use.
seed
Set to False to prevent Salt from seeding the new virtual machine.
nic
The nic profile to use, defaults to the "default" nic profile which
assumes a single network interface per vm associated with the "br0"
assumes a single network interface per VM associated with the "br0"
bridge on the master.
install
Set to False to prevent Salt from installing a minion on the new vm
Set to False to prevent Salt from installing a minion on the new VM
before it spins up.
disk
The disk profile to use
saltenv
The Salt environment to use
'''
__jid_event__.fire_event({'message': 'Searching for Hypervisors'}, 'progress')
data = query(hyper, quiet=True)
if hyper is not None:
salt.utils.warn_until(
'Carbon',
'Please use "host" instead of "hyper". The "hyper" argument will '
'be removed in the Carbon release of Salt'
)
host = hyper
__jid_event__.fire_event({'message': 'Searching for hosts'}, 'progress')
data = query(host, quiet=True)
# Check if the name is already deployed
for hyper in data:
if 'vm_info' in data[hyper]:
if name in data[hyper]['vm_info']:
__jid_event__.fire_event({'message': 'Virtual machine {0} is already deployed'.format(name)}, 'progress')
for node in data:
if 'vm_info' in data[node]:
if name in data[node]['vm_info']:
__jid_event__.fire_event(
{'message': 'Virtual machine {0} is already deployed'.format(name)},
'progress'
)
return 'fail'
if hyper is None:
hyper = _determine_hyper(data)
if host is None:
host = _determine_host(data)
if hyper not in data or not hyper:
__jid_event__.fire_event({'message': 'Hypervisor {0} was not found'.format(hyper)}, 'progress')
if host not in data or not host:
__jid_event__.fire_event(
{'message': 'Host {0} was not found'.format(host)},
'progress'
)
return 'fail'
pub_key = None
priv_key = None
if seed:
__jid_event__.fire_event({'message': 'Minion will be preseeded'}, 'progress')
kv_ = salt.utils.virt.VirtKey(hyper, name, __opts__)
kv_.authorize()
priv_key, pub_key = salt.utils.cloud.gen_keys()
accepted_key = os.path.join(__opts__['pki_dir'], 'minions', name)
with salt.utils.fopen(accepted_key, 'w') as fp_:
fp_.write(pub_key)
client = salt.client.get_local_client(__opts__['conf_file'])
__jid_event__.fire_event({'message': 'Creating VM {0} on hypervisor {1}'.format(name, hyper)}, 'progress')
__jid_event__.fire_event(
{'message': 'Creating VM {0} on host {1}'.format(name, host)},
'progress'
)
try:
cmd_ret = client.cmd_iter(
hyper,
host,
'virt.init',
[
name,
cpu,
mem,
image,
'seed={0}'.format(seed),
'nic={0}'.format(nic),
'install={0}'.format(install),
nic,
hypervisor,
start,
disk,
saltenv,
seed,
install,
pub_key,
priv_key,
],
timeout=600)
except SaltClientError as client_error:
@ -253,13 +339,13 @@ def init(
print('VM {0} initialization failed. Returned error: {1}'.format(name, ret[minion_id]['ret']))
return 'fail'
__jid_event__.fire_event({'message': 'VM {0} initialized on hypervisor {1}'.format(name, hyper)}, 'progress')
__jid_event__.fire_event({'message': 'VM {0} initialized on host {1}'.format(name, host)}, 'progress')
return 'good'
def vm_info(name, quiet=False):
'''
Return the information on the named vm
Return the information on the named VM
'''
data = query(quiet=True)
return _find_vm(name, data, quiet)
@ -267,18 +353,18 @@ def vm_info(name, quiet=False):
def reset(name):
'''
Force power down and restart an existing vm
Force power down and restart an existing VM
'''
ret = {}
client = salt.client.get_local_client(__opts__['conf_file'])
data = vm_info(name, quiet=True)
if not data:
__jid_event__.fire_event({'message': 'Failed to find vm {0} to reset'.format(name)}, 'progress')
__jid_event__.fire_event({'message': 'Failed to find VM {0} to reset'.format(name)}, 'progress')
return 'fail'
hyper = next(six.iterkeys(data))
host = next(six.iterkeys(data))
try:
cmd_ret = client.cmd_iter(
hyper,
host,
'virt.reset',
[name],
timeout=600)
@ -298,15 +384,15 @@ def start(name):
client = salt.client.get_local_client(__opts__['conf_file'])
data = vm_info(name, quiet=True)
if not data:
__jid_event__.fire_event({'message': 'Failed to find vm {0} to start'.format(name)}, 'progress')
__jid_event__.fire_event({'message': 'Failed to find VM {0} to start'.format(name)}, 'progress')
return 'fail'
hyper = next(six.iterkeys(data))
if data[hyper][name]['state'] == 'running':
host = next(six.iterkeys(data))
if data[host][name]['state'] == 'running':
print('VM {0} is already running'.format(name))
return 'bad state'
try:
cmd_ret = client.cmd_iter(
hyper,
host,
'virt.start',
[name],
timeout=600)
@ -326,15 +412,15 @@ def force_off(name):
client = salt.client.get_local_client(__opts__['conf_file'])
data = vm_info(name, quiet=True)
if not data:
print('Failed to find vm {0} to destroy'.format(name))
print('Failed to find VM {0} to destroy'.format(name))
return 'fail'
hyper = next(six.iterkeys(data))
if data[hyper][name]['state'] == 'shutdown':
host = next(six.iterkeys(data))
if data[host][name]['state'] == 'shutdown':
print('VM {0} is already shutdown'.format(name))
return'bad state'
try:
cmd_ret = client.cmd_iter(
hyper,
host,
'virt.destroy',
[name],
timeout=600)
@ -348,18 +434,18 @@ def force_off(name):
def purge(name, delete_key=True):
'''
Destroy the named vm
Destroy the named VM
'''
ret = {}
client = salt.client.get_local_client(__opts__['conf_file'])
data = vm_info(name, quiet=True)
if not data:
__jid_event__.fire_event({'error': 'Failed to find vm {0} to purge'.format(name)}, 'progress')
__jid_event__.fire_event({'error': 'Failed to find VM {0} to purge'.format(name)}, 'progress')
return 'fail'
hyper = next(six.iterkeys(data))
host = next(six.iterkeys(data))
try:
cmd_ret = client.cmd_iter(
hyper,
host,
'virt.purge',
[name, True],
timeout=600)
@ -370,6 +456,7 @@ def purge(name, delete_key=True):
ret.update(comp)
if delete_key:
log.debug('Deleting key {0}'.format(name))
skey = salt.key.Key(__opts__)
skey.delete_key(name)
__jid_event__.fire_event({'message': 'Purged VM {0}'.format(name)}, 'progress')
@ -378,7 +465,7 @@ def purge(name, delete_key=True):
def pause(name):
'''
Pause the named vm
Pause the named VM
'''
ret = {}
client = salt.client.get_local_client(__opts__['conf_file'])
@ -387,13 +474,13 @@ def pause(name):
if not data:
__jid_event__.fire_event({'error': 'Failed to find VM {0} to pause'.format(name)}, 'progress')
return 'fail'
hyper = next(six.iterkeys(data))
if data[hyper][name]['state'] == 'paused':
host = next(six.iterkeys(data))
if data[host][name]['state'] == 'paused':
__jid_event__.fire_event({'error': 'VM {0} is already paused'.format(name)}, 'progress')
return 'bad state'
try:
cmd_ret = client.cmd_iter(
hyper,
host,
'virt.pause',
[name],
timeout=600)
@ -407,7 +494,7 @@ def pause(name):
def resume(name):
'''
Resume a paused vm
Resume a paused VM
'''
ret = {}
client = salt.client.get_local_client(__opts__['conf_file'])
@ -415,13 +502,13 @@ def resume(name):
if not data:
__jid_event__.fire_event({'error': 'Failed to find VM {0} to pause'.format(name)}, 'progress')
return 'not found'
hyper = next(six.iterkeys(data))
if data[hyper][name]['state'] != 'paused':
host = next(six.iterkeys(data))
if data[host][name]['state'] != 'paused':
__jid_event__.fire_event({'error': 'VM {0} is not paused'.format(name)}, 'progress')
return 'bad state'
try:
cmd_ret = client.cmd_iter(
hyper,
host,
'virt.resume',
[name],
timeout=600)
@ -435,36 +522,36 @@ def resume(name):
def migrate(name, target=''):
'''
Migrate a vm from one hypervisor to another. This routine will just start
Migrate a VM from one host to another. This routine will just start
the migration and display information on how to look up the progress.
'''
client = salt.client.get_local_client(__opts__['conf_file'])
data = query(quiet=True)
origin_data = _find_vm(name, data, quiet=True)
try:
origin_hyper = list(origin_data.keys())[0]
origin_host = list(origin_data.keys())[0]
except IndexError:
__jid_event__.fire_event({'error': 'Named vm {0} was not found to migrate'.format(name)}, 'progress')
__jid_event__.fire_event({'error': 'Named VM {0} was not found to migrate'.format(name)}, 'progress')
return ''
disks = origin_data[origin_hyper][name]['disks']
disks = origin_data[origin_host][name]['disks']
if not origin_data:
__jid_event__.fire_event({'error': 'Named vm {0} was not found to migrate'.format(name)}, 'progress')
__jid_event__.fire_event({'error': 'Named VM {0} was not found to migrate'.format(name)}, 'progress')
return ''
if not target:
target = _determine_hyper(data, origin_hyper)
target = _determine_host(data, origin_host)
if target not in data:
__jid_event__.fire_event({'error': 'Target hypervisor {0} not found'.format(origin_data)}, 'progress')
__jid_event__.fire_event({'error': 'Target host {0} not found'.format(origin_data)}, 'progress')
return ''
try:
client.cmd(target, 'virt.seed_non_shared_migrate', [disks, True])
jid = client.cmd_async(origin_hyper,
jid = client.cmd_async(origin_host,
'virt.migrate_non_shared',
[name, target])
except SaltClientError as client_error:
return 'Virtual machine {0} could not be migrated: {1}'.format(name, client_error)
msg = ('The migration of virtual machine {0} to hypervisor {1} has begun, '
msg = ('The migration of virtual machine {0} to host {1} has begun, '
'and can be tracked via jid {2}. The ``salt-run virt.query`` '
'runner can also be used, the target vm will be shown as paused '
'runner can also be used, the target VM will be shown as paused '
'until the migration is complete.').format(name, target, jid)
__jid_event__.fire_event({'message': msg}, 'progress')