def _dataset_present(dataset_type, name, volume_size=None, sparse=False, create_parent=False, properties=None, cloned_from=None):
    '''
    internal handler for filesystem_present/volume_present

    dataset_type : string
        volume or filesystem
    name : string
        name of volume
    volume_size : string
        size of volume
    sparse : boolean
        create sparse volume
    create_parent : boolean
        creates all the non-existing parent datasets.
        any property specified on the command line using the -o option is ignored.
    cloned_from : string
        name of snapshot to clone
    properties : dict
        additional zfs properties (-o)

    .. note::
        ``cloned_from`` is only use if the volume does not exist yet,
        when ``cloned_from`` is set after the volume exists it will be ignored.

    .. note::
        Properties do not get cloned, if you specify the properties in the state file
        they will be applied on a subsequent run.

        ``volume_size`` is considered a property, so the volume's size will be
        corrected when the properties get updated if it differs from the
        original volume.

        The sparse parameter is ignored when using ``cloned_from``.

    '''
    ret = {'name': name,
           'changes': {},
           'result': True,
           'comment': ''}

    ## fallback dataset_type to filesystem if out of range
    if dataset_type not in ['filesystem', 'volume']:
        dataset_type = 'filesystem'

    ## ensure properties are zfs values
    if volume_size:
        volume_size = __utils__['zfs.from_size'](volume_size)
    if properties:
        properties = __utils__['zfs.from_auto_dict'](properties)
    elif properties is None:
        properties = {}

    ## log configuration
    log.debug('zfs.%s_present::%s::config::volume_size = %s',
              dataset_type, name, volume_size)
    log.debug('zfs.%s_present::%s::config::sparse = %s',
              dataset_type, name, sparse)
    log.debug('zfs.%s_present::%s::config::create_parent = %s',
              dataset_type, name, create_parent)
    log.debug('zfs.%s_present::%s::config::cloned_from = %s',
              dataset_type, name, cloned_from)
    log.debug('zfs.%s_present::%s::config::properties = %s',
              dataset_type, name, properties)

    ## check we have valid filesystem name/volume name/clone snapshot
    if not __utils__['zfs.is_dataset'](name):
        ret['result'] = False
        ret['comment'] = 'invalid dataset name: {0}'.format(name)
        return ret

    if cloned_from and not __utils__['zfs.is_snapshot'](cloned_from):
        ret['result'] = False
        ret['comment'] = '{0} is not a snapshot'.format(cloned_from)
        return ret

    ## ensure dataset is in correct state
    ## NOTE: update the dataset
    if __salt__['zfs.exists'](name, **{'type': dataset_type}):
        ## NOTE: fetch current volume properties
        properties_current = __salt__['zfs.get'](
            name,
            type=dataset_type,
            fields='value',
            depth=0,
            parsable=True,
        ).get(name, OrderedDict())

        ## NOTE: add volsize to properties
        if volume_size:
            properties['volsize'] = volume_size

        ## NOTE: build list of properties to update
        properties_update = []
        for prop in properties:
            ## NOTE: skip unexisting properties
            if prop not in properties_current:
                log.warning('zfs.%s_present::%s::update - unknown property: %s',
                    dataset_type, name, prop)
                continue

            ## NOTE: compare current and wanted value
            if properties_current[prop]['value'] != properties[prop]:
                properties_update.append(prop)

        ## NOTE: update pool properties
        for prop in properties_update:
            if not __opts__['test']:
                mod_res = __salt__['zfs.set'](name, **{prop: properties[prop]})
            else:
                mod_res = OrderedDict([('set', True)])

            if mod_res['set']:
                if name not in ret['changes']:
                    ret['changes'][name] = {}
                ret['changes'][name][prop] = properties[prop]
            else:
                ret['result'] = False
                if ret['comment'] == '':
                    ret['comment'] = 'The following properties were not updated:'
                ret['comment'] = '{0} {1}'.format(ret['comment'], prop)

        ## NOTE: update comment
        if ret['result'] and name in ret['changes']:
            ret['comment'] = '{0} {1} was updated'.format(dataset_type, name)
        elif ret['result']:
            ret['comment'] = '{0} {1} is uptodate'.format(dataset_type, name)
        else:
            ret['comment'] = '{0} {1} failed to be updated'.format(dataset_type, name)

    ## NOTE: create or clone the dataset
    else:
        mod_res_action = 'cloned' if cloned_from else 'created'
        if __opts__['test']:
            ## NOTE: pretend to create/clone
            mod_res = OrderedDict([
                (mod_res_action, True),
            ])
        elif cloned_from:
            ## NOTE: add volsize to properties
            if volume_size:
                properties['volsize'] = volume_size

            ## NOTE: clone the dataset
            mod_res = __salt__['zfs.clone'](cloned_from, name, **{
                'create_parent': create_parent,
                'properties': properties,
            })
        else:
            ## NOTE: create the dataset
            mod_res = __salt__['zfs.create'](name, **{
                'create_parent': create_parent,
                'properties': properties,
                'volume_size': volume_size,
                'sparse': sparse,
            })

        ret['result'] = mod_res[mod_res_action]
        if ret['result']:
            ret['changes'][name] = mod_res_action
            if properties:
                ret['changes'][name] = properties
            ret['comment'] = '{0} {1} was {2}'.format(
                dataset_type,
                name,
                mod_res_action,
            )
        else:
            ret['comment'] = 'failed to {0} {1} {2}'.format(
                mod_res_action[:-1],
                dataset_type,
                name,
            )
            if 'error' in mod_res:
                ret['comment'] = mod_res['error']

    return ret
def _dataset_present ( dataset_type , name , volume_size = None , sparse = False , create_parent = False , properties = None , cloned_from = None ) : ret = { 'name' : name , 'changes' : { } , 'result' : True , 'comment' : '' } if dataset_type not in [ 'filesystem' , 'volume' ] : dataset_type = 'filesystem' if volume_size : volume_size = __utils__ [ 'zfs.from_size' ] ( volume_size ) if properties : properties = __utils__ [ 'zfs.from_auto_dict' ] ( properties ) elif properties is None : properties = { } log . debug ( 'zfs.%s_present::%s::config::volume_size = %s' , dataset_type , name , volume_size ) log . debug ( 'zfs.%s_present::%s::config::sparse = %s' , dataset_type , name , sparse ) log . debug ( 'zfs.%s_present::%s::config::create_parent = %s' , dataset_type , name , create_parent ) log . debug ( 'zfs.%s_present::%s::config::cloned_from = %s' , dataset_type , name , cloned_from ) log . debug ( 'zfs.%s_present::%s::config::properties = %s' , dataset_type , name , properties ) if not __utils__ [ 'zfs.is_dataset' ] ( name ) : ret [ 'result' ] = False ret [ 'comment' ] = 'invalid dataset name: {0}' . format ( name ) return ret if cloned_from and not __utils__ [ 'zfs.is_snapshot' ] ( cloned_from ) : ret [ 'result' ] = False ret [ 'comment' ] = '{0} is not a snapshot' . format ( cloned_from ) return ret if __salt__ [ 'zfs.exists' ] ( name , ** { 'type' : dataset_type } ) : properties_current = __salt__ [ 'zfs.get' ] ( name , type = dataset_type , fields = 'value' , depth = 0 , parsable = True , ) . get ( name , OrderedDict ( ) ) if volume_size : properties [ 'volsize' ] = volume_size properties_update = [ ] for prop in properties : if prop not in properties_current : log . warning ( 'zfs.%s_present::%s::update - unknown property: %s' , dataset_type , name , prop ) continue if properties_current [ prop ] [ 'value' ] != properties [ prop ] : properties_update . append ( prop ) for prop in properties_update : if not __opts__ [ 'test' ] : mod_res = __salt__ [ 'zfs.set' ] ( name , ** { prop : properties [ prop ] } ) else : mod_res = OrderedDict ( [ ( 'set' , True ) ] ) if mod_res [ 'set' ] : if name not in ret [ 'changes' ] : ret [ 'changes' ] [ name ] = { } ret [ 'changes' ] [ name ] [ prop ] = properties [ prop ] else : ret [ 'result' ] = False if ret [ 'comment' ] == '' : ret [ 'comment' ] = 'The following properties were not updated:' ret [ 'comment' ] = '{0} {1}' . format ( ret [ 'comment' ] , prop ) if ret [ 'result' ] and name in ret [ 'changes' ] : ret [ 'comment' ] = '{0} {1} was updated' . format ( dataset_type , name ) elif ret [ 'result' ] : ret [ 'comment' ] = '{0} {1} is uptodate' . format ( dataset_type , name ) else : ret [ 'comment' ] = '{0} {1} failed to be updated' . format ( dataset_type , name ) else : mod_res_action = 'cloned' if cloned_from else 'created' if __opts__ [ 'test' ] : mod_res = OrderedDict ( [ ( mod_res_action , True ) , ] ) elif cloned_from : if volume_size : properties [ 'volsize' ] = volume_size mod_res = __salt__ [ 'zfs.clone' ] ( cloned_from , name , ** { 'create_parent' : create_parent , 'properties' : properties , } ) else : mod_res = __salt__ [ 'zfs.create' ] ( name , ** { 'create_parent' : create_parent , 'properties' : properties , 'volume_size' : volume_size , 'sparse' : sparse , } ) ret [ 'result' ] = mod_res [ mod_res_action ] if ret [ 'result' ] : ret [ 'changes' ] [ name ] = mod_res_action if properties : ret [ 'changes' ] [ name ] = properties ret [ 'comment' ] = '{0} {1} was {2}' . format ( dataset_type , name , mod_res_action , ) else : ret [ 'comment' ] = 'failed to {0} {1} {2}' . format ( mod_res_action [ : - 1 ] , dataset_type , name , ) if 'error' in mod_res : ret [ 'comment' ] = mod_res [ 'error' ] return ret
internal handler for filesystem_present/volume_present

    dataset_type : string
        volume or filesystem
    name : string
        name of volume
    volume_size : string
        size of volume
    sparse : boolean
        create sparse volume
    create_parent : boolean
        creates all the non-existing parent datasets.
        any property specified on the command line using the -o option is ignored.
    cloned_from : string
        name of snapshot to clone
    properties : dict
        additional zfs properties (-o)

    .. note::
        ``cloned_from`` is only use if the volume does not exist yet,
        when ``cloned_from`` is set after the volume exists it will be ignored.

    .. note::
        Properties do not get cloned, if you specify the properties in the state file
        they will be applied on a subsequent run.

        ``volume_size`` is considered a property, so the volume's size will be
        corrected when the properties get updated if it differs from the
        original volume.

        The sparse parameter is ignored when using ``cloned_from``.