%PDF- %PDF-
Direktori : /lib/python2.7/site-packages/salt/modules/ |
Current File : //lib/python2.7/site-packages/salt/modules/smartos_vmadm.py |
# -*- coding: utf-8 -*- ''' Module for running vmadm command on SmartOS ''' from __future__ import absolute_import, unicode_literals, print_function # Import Python libs import logging import os try: from shlex import quote as _quote_args # pylint: disable=E0611 except ImportError: from pipes import quote as _quote_args # Import Salt libs import salt.utils.args import salt.utils.files import salt.utils.json import salt.utils.path import salt.utils.platform import salt.utils.stringutils from salt.utils.odict import OrderedDict # Import 3rd-party libs from salt.ext import six log = logging.getLogger(__name__) # Function aliases __func_alias__ = { 'list_vms': 'list' } # Define the module's virtual name __virtualname__ = 'vmadm' def __virtual__(): ''' Provides vmadm on SmartOS ''' if salt.utils.platform.is_smartos_globalzone() and \ salt.utils.path.which('vmadm') and \ salt.utils.path.which('zfs'): return __virtualname__ return ( False, '{0} module can only be loaded on SmartOS compute nodes'.format( __virtualname__ ) ) def _exit_status(retcode): ''' Translate exit status of vmadm ''' ret = {0: 'Successful completion.', 1: 'An error occurred.', 2: 'Usage error.'}[retcode] return ret def _create_update_from_file(mode='create', uuid=None, path=None): ''' Create vm from file ''' ret = {} if not os.path.isfile(path) or path is None: ret['Error'] = 'File ({0}) does not exists!'.format(path) return ret # vmadm validate create|update [-f <filename>] cmd = 'vmadm validate {mode} {brand} -f {path}'.format( mode=mode, brand=get(uuid)['brand'] if uuid is not None else '', path=path ) res = __salt__['cmd.run_all'](cmd) retcode = res['retcode'] if retcode != 0: ret['Error'] = _exit_status(retcode) if 'stderr' in res: if res['stderr'][0] == '{': ret['Error'] = salt.utils.json.loads(res['stderr']) else: ret['Error'] = res['stderr'] return ret # vmadm create|update [-f <filename>] cmd = 'vmadm {mode} {uuid} -f {path}'.format( mode=mode, uuid=uuid if uuid is not None else '', path=path ) res = __salt__['cmd.run_all'](cmd) retcode = res['retcode'] if retcode != 0: ret['Error'] = _exit_status(retcode) if 'stderr' in res: if res['stderr'][0] == '{': ret['Error'] = salt.utils.json.loads(res['stderr']) else: ret['Error'] = res['stderr'] return ret else: if res['stderr'].startswith('Successfully created VM'): return res['stderr'][24:] return True def _create_update_from_cfg(mode='create', uuid=None, vmcfg=None): ''' Create vm from configuration ''' ret = {} # write json file vmadm_json_file = __salt__['temp.file'](prefix='vmadm-') with salt.utils.files.fopen(vmadm_json_file, 'w') as vmadm_json: salt.utils.json.dump(vmcfg, vmadm_json) # vmadm validate create|update [-f <filename>] cmd = 'vmadm validate {mode} {brand} -f {vmadm_json_file}'.format( mode=mode, brand=get(uuid)['brand'] if uuid is not None else '', vmadm_json_file=vmadm_json_file ) res = __salt__['cmd.run_all'](cmd, python_shell=True) retcode = res['retcode'] if retcode != 0: ret['Error'] = _exit_status(retcode) if 'stderr' in res: if res['stderr'][0] == '{': ret['Error'] = salt.utils.json.loads(res['stderr']) else: ret['Error'] = res['stderr'] return ret # vmadm create|update [-f <filename>] cmd = 'vmadm {mode} {uuid} -f {vmadm_json_file}'.format( mode=mode, uuid=uuid if uuid is not None else '', vmadm_json_file=vmadm_json_file ) res = __salt__['cmd.run_all'](cmd, python_shell=True) retcode = res['retcode'] if retcode != 0: ret['Error'] = _exit_status(retcode) if 'stderr' in res: if res['stderr'][0] == '{': ret['Error'] = salt.utils.json.loads(res['stderr']) else: ret['Error'] = res['stderr'] return ret else: # cleanup json file (only when successful to help troubleshooting) salt.utils.files.safe_rm(vmadm_json_file) # return uuid if res['stderr'].startswith('Successfully created VM'): return res['stderr'][24:] return True def start(vm, options=None, key='uuid'): ''' Start a vm vm : string vm to be started options : string optional additional options key : string [uuid|alias|hostname] value type of 'vm' parameter CLI Example: .. code-block:: bash salt '*' vmadm.start 186da9ab-7392-4f55-91a5-b8f1fe770543 salt '*' vmadm.start 186da9ab-7392-4f55-91a5-b8f1fe770543 'order=c,once=d cdrom=/path/to/image.iso,ide' salt '*' vmadm.start vm=nacl key=alias salt '*' vmadm.start vm=nina.example.org key=hostname ''' ret = {} if key not in ['uuid', 'alias', 'hostname']: ret['Error'] = 'Key must be either uuid, alias or hostname' return ret vm = lookup('{0}={1}'.format(key, vm), one=True) if 'Error' in vm: return vm # vmadm start <uuid> [option=value ...] cmd = 'vmadm start {uuid} {options}'.format( uuid=vm, options=options if options else '' ) res = __salt__['cmd.run_all'](cmd) retcode = res['retcode'] if retcode != 0: ret['Error'] = res['stderr'] if 'stderr' in res else _exit_status(retcode) return ret return True def stop(vm, force=False, key='uuid'): ''' Stop a vm vm : string vm to be stopped force : boolean force stop of vm if true key : string [uuid|alias|hostname] value type of 'vm' parameter CLI Example: .. code-block:: bash salt '*' vmadm.stop 186da9ab-7392-4f55-91a5-b8f1fe770543 salt '*' vmadm.stop 186da9ab-7392-4f55-91a5-b8f1fe770543 True salt '*' vmadm.stop vm=nacl key=alias salt '*' vmadm.stop vm=nina.example.org key=hostname ''' ret = {} if key not in ['uuid', 'alias', 'hostname']: ret['Error'] = 'Key must be either uuid, alias or hostname' return ret vm = lookup('{0}={1}'.format(key, vm), one=True) if 'Error' in vm: return vm # vmadm stop <uuid> [-F] cmd = 'vmadm stop {force} {uuid}'.format( force='-F' if force else '', uuid=vm ) res = __salt__['cmd.run_all'](cmd) retcode = res['retcode'] if retcode != 0: ret['Error'] = _exit_status(retcode) return ret return True def reboot(vm, force=False, key='uuid'): ''' Reboot a vm vm : string vm to be rebooted force : boolean force reboot of vm if true key : string [uuid|alias|hostname] value type of 'vm' parameter CLI Example: .. code-block:: bash salt '*' vmadm.reboot 186da9ab-7392-4f55-91a5-b8f1fe770543 salt '*' vmadm.reboot 186da9ab-7392-4f55-91a5-b8f1fe770543 True salt '*' vmadm.reboot vm=nacl key=alias salt '*' vmadm.reboot vm=nina.example.org key=hostname ''' ret = {} if key not in ['uuid', 'alias', 'hostname']: ret['Error'] = 'Key must be either uuid, alias or hostname' return ret vm = lookup('{0}={1}'.format(key, vm), one=True) if 'Error' in vm: return vm # vmadm reboot <uuid> [-F] cmd = 'vmadm reboot {force} {uuid}'.format( force='-F' if force else '', uuid=vm ) res = __salt__['cmd.run_all'](cmd) retcode = res['retcode'] if retcode != 0: ret['Error'] = res['stderr'] if 'stderr' in res else _exit_status(retcode) return ret return True def list_vms(search=None, sort=None, order='uuid,type,ram,state,alias', keyed=True): ''' Return a list of VMs search : string vmadm filter property sort : string vmadm sort (-s) property order : string vmadm order (-o) property -- Default: uuid,type,ram,state,alias keyed : boolean specified if the output should be an array (False) or dict (True) For a dict the key is the first item from the order parameter. Note: If key is not unique last vm wins. CLI Example: .. code-block:: bash salt '*' vmadm.list salt '*' vmadm.list order=alias,ram,cpu_cap sort=-ram,-cpu_cap salt '*' vmadm.list search='type=KVM' ''' ret = {} # vmadm list [-p] [-H] [-o field,...] [-s field,...] [field=value ...] cmd = 'vmadm list -p -H {order} {sort} {search}'.format( order='-o {0}'.format(order) if order else '', sort='-s {0}'.format(sort) if sort else '', search=search if search else '' ) res = __salt__['cmd.run_all'](cmd) retcode = res['retcode'] result = OrderedDict() if keyed else [] if retcode != 0: ret['Error'] = res['stderr'] if 'stderr' in res else _exit_status(retcode) return ret fields = order.split(',') for vm in res['stdout'].splitlines(): vm_data = OrderedDict() vm = vm.split(':') if keyed: for field in fields: if fields.index(field) == 0: continue vm_data[field.strip()] = vm[fields.index(field)].strip() result[vm[0]] = vm_data else: if len(vm) > 1: for field in fields: vm_data[field.strip()] = vm[fields.index(field)].strip() else: vm_data = vm[0] result.append(vm_data) return result def lookup(search=None, order=None, one=False): ''' Return a list of VMs using lookup search : string vmadm filter property order : string vmadm order (-o) property -- Default: uuid,type,ram,state,alias one : boolean return only one result (vmadm's -1) CLI Example: .. code-block:: bash salt '*' vmadm.lookup search='state=running' salt '*' vmadm.lookup search='state=running' order=uuid,alias,hostname salt '*' vmadm.lookup search='alias=nacl' one=True ''' ret = {} # vmadm lookup [-j|-1] [-o field,...] [field=value ...] cmd = 'vmadm lookup {one} {order} {search}'.format( one='-1' if one else '-j', order='-o {0}'.format(order) if order else '', search=search if search else '' ) res = __salt__['cmd.run_all'](cmd) retcode = res['retcode'] result = [] if retcode != 0: ret['Error'] = res['stderr'] if 'stderr' in res else _exit_status(retcode) return ret if one: result = res['stdout'] else: for vm in salt.utils.json.loads(res['stdout']): result.append(vm) return result def sysrq(vm, action='nmi', key='uuid'): ''' Send non-maskable interrupt to vm or capture a screenshot vm : string vm to be targeted action : string nmi or screenshot -- Default: nmi key : string [uuid|alias|hostname] value type of 'vm' parameter CLI Example: .. code-block:: bash salt '*' vmadm.sysrq 186da9ab-7392-4f55-91a5-b8f1fe770543 nmi salt '*' vmadm.sysrq 186da9ab-7392-4f55-91a5-b8f1fe770543 screenshot salt '*' vmadm.sysrq nacl nmi key=alias ''' ret = {} if key not in ['uuid', 'alias', 'hostname']: ret['Error'] = 'Key must be either uuid, alias or hostname' return ret if action not in ['nmi', 'screenshot']: ret['Error'] = 'Action must be either nmi or screenshot' return ret vm = lookup('{0}={1}'.format(key, vm), one=True) if 'Error' in vm: return vm # vmadm sysrq <uuid> <nmi|screenshot> cmd = 'vmadm sysrq {uuid} {action}'.format( uuid=vm, action=action ) res = __salt__['cmd.run_all'](cmd) retcode = res['retcode'] if retcode != 0: ret['Error'] = res['stderr'] if 'stderr' in res else _exit_status(retcode) return ret return True def delete(vm, key='uuid'): ''' Delete a vm vm : string vm to be deleted key : string [uuid|alias|hostname] value type of 'vm' parameter CLI Example: .. code-block:: bash salt '*' vmadm.delete 186da9ab-7392-4f55-91a5-b8f1fe770543 salt '*' vmadm.delete nacl key=alias ''' ret = {} if key not in ['uuid', 'alias', 'hostname']: ret['Error'] = 'Key must be either uuid, alias or hostname' return ret vm = lookup('{0}={1}'.format(key, vm), one=True) if 'Error' in vm: return vm # vmadm delete <uuid> cmd = 'vmadm delete {0}'.format(vm) res = __salt__['cmd.run_all'](cmd) retcode = res['retcode'] if retcode != 0: ret['Error'] = res['stderr'] if 'stderr' in res else _exit_status(retcode) return ret return True def get(vm, key='uuid'): ''' Output the JSON object describing a VM vm : string vm to be targeted key : string [uuid|alias|hostname] value type of 'vm' parameter CLI Example: .. code-block:: bash salt '*' vmadm.get 186da9ab-7392-4f55-91a5-b8f1fe770543 salt '*' vmadm.get nacl key=alias ''' ret = {} if key not in ['uuid', 'alias', 'hostname']: ret['Error'] = 'Key must be either uuid, alias or hostname' return ret vm = lookup('{0}={1}'.format(key, vm), one=True) if 'Error' in vm: return vm # vmadm get <uuid> cmd = 'vmadm get {0}'.format(vm) res = __salt__['cmd.run_all'](cmd) retcode = res['retcode'] if retcode != 0: ret['Error'] = res['stderr'] if 'stderr' in res else _exit_status(retcode) return ret return salt.utils.json.loads(res['stdout']) def info(vm, info_type='all', key='uuid'): ''' Lookup info on running kvm vm : string vm to be targeted info_type : string [all|block|blockstats|chardev|cpus|kvm|pci|spice|version|vnc] info type to return key : string [uuid|alias|hostname] value type of 'vm' parameter CLI Example: .. code-block:: bash salt '*' vmadm.info 186da9ab-7392-4f55-91a5-b8f1fe770543 salt '*' vmadm.info 186da9ab-7392-4f55-91a5-b8f1fe770543 vnc salt '*' vmadm.info nacl key=alias salt '*' vmadm.info nacl vnc key=alias ''' ret = {} if info_type not in ['all', 'block', 'blockstats', 'chardev', 'cpus', 'kvm', 'pci', 'spice', 'version', 'vnc']: ret['Error'] = 'Requested info_type is not available' return ret if key not in ['uuid', 'alias', 'hostname']: ret['Error'] = 'Key must be either uuid, alias or hostname' return ret vm = lookup('{0}={1}'.format(key, vm), one=True) if 'Error' in vm: return vm # vmadm info <uuid> [type,...] cmd = 'vmadm info {uuid} {type}'.format( uuid=vm, type=info_type ) res = __salt__['cmd.run_all'](cmd) retcode = res['retcode'] if retcode != 0: ret['Error'] = res['stderr'] if 'stderr' in res else _exit_status(retcode) return ret return salt.utils.json.loads(res['stdout']) def create_snapshot(vm, name, key='uuid'): ''' Create snapshot of a vm vm : string vm to be targeted name : string snapshot name The snapname must be 64 characters or less and must only contain alphanumeric characters and characters in the set [-_.:%] to comply with ZFS restrictions. key : string [uuid|alias|hostname] value type of 'vm' parameter CLI Example: .. code-block:: bash salt '*' vmadm.create_snapshot 186da9ab-7392-4f55-91a5-b8f1fe770543 baseline salt '*' vmadm.create_snapshot nacl baseline key=alias ''' ret = {} if key not in ['uuid', 'alias', 'hostname']: ret['Error'] = 'Key must be either uuid, alias or hostname' return ret vm = lookup('{0}={1}'.format(key, vm), one=True) if 'Error' in vm: return vm vmobj = get(vm) if 'datasets' in vmobj: ret['Error'] = 'VM cannot have datasets' return ret if vmobj['brand'] in ['kvm']: ret['Error'] = 'VM must be of type OS' return ret if vmobj['zone_state'] not in ['running']: # work around a vmadm bug ret['Error'] = 'VM must be running to take a snapshot' return ret # vmadm create-snapshot <uuid> <snapname> cmd = 'vmadm create-snapshot {uuid} {snapshot}'.format( snapshot=name, uuid=vm ) res = __salt__['cmd.run_all'](cmd) retcode = res['retcode'] if retcode != 0: ret['Error'] = res['stderr'] if 'stderr' in res else _exit_status(retcode) return ret return True def delete_snapshot(vm, name, key='uuid'): ''' Delete snapshot of a vm vm : string vm to be targeted name : string snapshot name The snapname must be 64 characters or less and must only contain alphanumeric characters and characters in the set [-_.:%] to comply with ZFS restrictions. key : string [uuid|alias|hostname] value type of 'vm' parameter CLI Example: .. code-block:: bash salt '*' vmadm.delete_snapshot 186da9ab-7392-4f55-91a5-b8f1fe770543 baseline salt '*' vmadm.delete_snapshot nacl baseline key=alias ''' ret = {} if key not in ['uuid', 'alias', 'hostname']: ret['Error'] = 'Key must be either uuid, alias or hostname' return ret vm = lookup('{0}={1}'.format(key, vm), one=True) if 'Error' in vm: return vm vmobj = get(vm) if 'datasets' in vmobj: ret['Error'] = 'VM cannot have datasets' return ret if vmobj['brand'] in ['kvm']: ret['Error'] = 'VM must be of type OS' return ret # vmadm delete-snapshot <uuid> <snapname> cmd = 'vmadm delete-snapshot {uuid} {snapshot}'.format( snapshot=name, uuid=vm ) res = __salt__['cmd.run_all'](cmd) retcode = res['retcode'] if retcode != 0: ret['Error'] = res['stderr'] if 'stderr' in res else _exit_status(retcode) return ret return True def rollback_snapshot(vm, name, key='uuid'): ''' Rollback snapshot of a vm vm : string vm to be targeted name : string snapshot name The snapname must be 64 characters or less and must only contain alphanumeric characters and characters in the set [-_.:%] to comply with ZFS restrictions. key : string [uuid|alias|hostname] value type of 'vm' parameter CLI Example: .. code-block:: bash salt '*' vmadm.rollback_snapshot 186da9ab-7392-4f55-91a5-b8f1fe770543 baseline salt '*' vmadm.rollback_snapshot nacl baseline key=alias ''' ret = {} if key not in ['uuid', 'alias', 'hostname']: ret['Error'] = 'Key must be either uuid, alias or hostname' return ret vm = lookup('{0}={1}'.format(key, vm), one=True) if 'Error' in vm: return vm vmobj = get(vm) if 'datasets' in vmobj: ret['Error'] = 'VM cannot have datasets' return ret if vmobj['brand'] in ['kvm']: ret['Error'] = 'VM must be of type OS' return ret # vmadm rollback-snapshot <uuid> <snapname> cmd = 'vmadm rollback-snapshot {uuid} {snapshot}'.format( snapshot=name, uuid=vm ) res = __salt__['cmd.run_all'](cmd) retcode = res['retcode'] if retcode != 0: ret['Error'] = res['stderr'] if 'stderr' in res else _exit_status(retcode) return ret return True def reprovision(vm, image, key='uuid'): ''' Reprovision a vm vm : string vm to be reprovisioned image : string uuid of new image key : string [uuid|alias|hostname] value type of 'vm' parameter CLI Example: .. code-block:: bash salt '*' vmadm.reprovision 186da9ab-7392-4f55-91a5-b8f1fe770543 c02a2044-c1bd-11e4-bd8c-dfc1db8b0182 salt '*' vmadm.reprovision nacl c02a2044-c1bd-11e4-bd8c-dfc1db8b0182 key=alias ''' ret = {} if key not in ['uuid', 'alias', 'hostname']: ret['Error'] = 'Key must be either uuid, alias or hostname' return ret vm = lookup('{0}={1}'.format(key, vm), one=True) if 'Error' in vm: return vm if image not in __salt__['imgadm.list'](): ret['Error'] = 'Image ({0}) is not present on this host'.format(image) return ret # vmadm reprovision <uuid> [-f <filename>] cmd = six.text_type('echo {image} | vmadm reprovision {uuid}').format( uuid=salt.utils.stringutils.to_unicode(vm), image=_quote_args(salt.utils.json.dumps({'image_uuid': image})) ) res = __salt__['cmd.run_all'](cmd, python_shell=True) retcode = res['retcode'] if retcode != 0: ret['Error'] = res['stderr'] if 'stderr' in res else _exit_status(retcode) return ret return True def create(from_file=None, **kwargs): ''' Create a new vm from_file : string json file to create the vm from -- if present, all other options will be ignored kwargs : string|int|... options to set for the vm CLI Example: .. code-block:: bash salt '*' vmadm.create from_file=/tmp/new_vm.json salt '*' vmadm.create image_uuid='...' alias='...' nics='[{ "nic_tag": "admin", "ip": "198.51.100.123", ...}, {...}]' [...] ''' ret = {} # prepare vmcfg vmcfg = {} kwargs = salt.utils.args.clean_kwargs(**kwargs) for k, v in six.iteritems(kwargs): vmcfg[k] = v if from_file: return _create_update_from_file('create', path=from_file) else: return _create_update_from_cfg('create', vmcfg=vmcfg) def update(vm, from_file=None, key='uuid', **kwargs): ''' Update a new vm vm : string vm to be updated from_file : string json file to update the vm with -- if present, all other options will be ignored key : string [uuid|alias|hostname] value type of 'vm' parameter kwargs : string|int|... options to update for the vm CLI Example: .. code-block:: bash salt '*' vmadm.update vm=186da9ab-7392-4f55-91a5-b8f1fe770543 from_file=/tmp/new_vm.json salt '*' vmadm.update vm=nacl key=alias from_file=/tmp/new_vm.json salt '*' vmadm.update vm=186da9ab-7392-4f55-91a5-b8f1fe770543 max_physical_memory=1024 ''' ret = {} # prepare vmcfg vmcfg = {} kwargs = salt.utils.args.clean_kwargs(**kwargs) for k, v in six.iteritems(kwargs): vmcfg[k] = v if key not in ['uuid', 'alias', 'hostname']: ret['Error'] = 'Key must be either uuid, alias or hostname' return ret uuid = lookup('{0}={1}'.format(key, vm), one=True) if 'Error' in uuid: return uuid if from_file: return _create_update_from_file('update', uuid, path=from_file) else: return _create_update_from_cfg('update', uuid, vmcfg=vmcfg) def send(vm, target, key='uuid'): ''' Send a vm to a directory vm : string vm to be sent target : string target directory key : string [uuid|alias|hostname] value type of 'vm' parameter CLI Example: .. code-block:: bash salt '*' vmadm.send 186da9ab-7392-4f55-91a5-b8f1fe770543 /opt/backups salt '*' vmadm.send vm=nacl target=/opt/backups key=alias ''' ret = {} if key not in ['uuid', 'alias', 'hostname']: ret['Error'] = 'Key must be either uuid, alias or hostname' return ret if not os.path.isdir(target): ret['Error'] = 'Target must be a directory or host' return ret vm = lookup('{0}={1}'.format(key, vm), one=True) if 'Error' in vm: return vm # vmadm send <uuid> [target] cmd = 'vmadm send {uuid} > {target}'.format( uuid=vm, target=os.path.join(target, '{0}.vmdata'.format(vm)) ) res = __salt__['cmd.run_all'](cmd, python_shell=True) retcode = res['retcode'] if retcode != 0: ret['Error'] = res['stderr'] if 'stderr' in res else _exit_status(retcode) return ret vmobj = get(vm) if 'datasets' not in vmobj: return True log.warning('one or more datasets detected, this is not supported!') log.warning('trying to zfs send datasets...') for dataset in vmobj['datasets']: name = dataset.split('/') name = name[-1] cmd = 'zfs send {dataset} > {target}'.format( dataset=dataset, target=os.path.join(target, '{0}-{1}.zfsds'.format(vm, name)) ) res = __salt__['cmd.run_all'](cmd, python_shell=True) retcode = res['retcode'] if retcode != 0: ret['Error'] = res['stderr'] if 'stderr' in res else _exit_status(retcode) return ret return True def receive(uuid, source): ''' Receive a vm from a directory uuid : string uuid of vm to be received source : string source directory CLI Example: .. code-block:: bash salt '*' vmadm.receive 186da9ab-7392-4f55-91a5-b8f1fe770543 /opt/backups ''' ret = {} if not os.path.isdir(source): ret['Error'] = 'Source must be a directory or host' return ret if not os.path.exists(os.path.join(source, '{0}.vmdata'.format(uuid))): ret['Error'] = 'Unknow vm with uuid in {0}'.format(source) return ret # vmadm receive cmd = 'vmadm receive < {source}'.format( source=os.path.join(source, '{0}.vmdata'.format(uuid)) ) res = __salt__['cmd.run_all'](cmd, python_shell=True) retcode = res['retcode'] if retcode != 0 and not res['stderr'].endswith('datasets'): ret['Error'] = res['stderr'] if 'stderr' in res else _exit_status(retcode) return ret vmobj = get(uuid) if 'datasets' not in vmobj: return True log.warning('one or more datasets detected, this is not supported!') log.warning('trying to restore datasets, mountpoints will need to be set again...') for dataset in vmobj['datasets']: name = dataset.split('/') name = name[-1] cmd = 'zfs receive {dataset} < {source}'.format( dataset=dataset, source=os.path.join(source, '{0}-{1}.zfsds'.format(uuid, name)) ) res = __salt__['cmd.run_all'](cmd, python_shell=True) retcode = res['retcode'] if retcode != 0: ret['Error'] = res['stderr'] if 'stderr' in res else _exit_status(retcode) return ret cmd = 'vmadm install {0}'.format(uuid) res = __salt__['cmd.run_all'](cmd, python_shell=True) retcode = res['retcode'] if retcode != 0 and not res['stderr'].endswith('datasets'): ret['Error'] = res['stderr'] if 'stderr' in res else _exit_status(retcode) return ret return True # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4