docs: def present(name, properties=None, filesystem_properties=None, layout=None, config=None):
      '''
      ensure storage pool is present on the system
  
      name : string
          name of storage pool
      properties : dict
          optional set of properties to set for the storage pool
      filesystem_properties : dict
          optional set of filesystem properties to set for the storage pool (creation only)
      layout: dict
          disk layout to use if the pool does not exist (creation only)
      config : dict
          fine grain control over this state
  
      .. note::
  
          The following configuration properties can be toggled in the config parameter.
            - import (true) - try to import the pool before creating it if absent
            - import_dirs (None) - specify additional locations to scan for devices on import (comma-seperated)
            - device_dir (None, SunOS=/dev/dsk, Linux=/dev) - specify device directory to prepend for none
              absolute device paths
            - force (false) - try to force the import or creation
  
      .. note::
  
          It is no longer needed to give a unique name to each top-level vdev, the old
          layout format is still supported but no longer recommended.
  
          .. code-block:: yaml
  
              - mirror:
                - /tmp/vdisk3
                - /tmp/vdisk2
              - mirror:
                - /tmp/vdisk0
                - /tmp/vdisk1
  
          The above yaml will always result in the following zpool create:
  
          .. code-block:: bash
  
              zpool create mypool mirror /tmp/vdisk3 /tmp/vdisk2 mirror /tmp/vdisk0 /tmp/vdisk1
  
      .. warning::
  
          The legacy format is also still supported but not recommended,
          because ID's inside the layout dict must be unique they need to have a suffix.
  
          .. code-block:: yaml
  
              mirror-0:
                /tmp/vdisk3
                /tmp/vdisk2
              mirror-1:
                /tmp/vdisk0
                /tmp/vdisk1
  
      .. warning::
  
          Pay attention to the order of your dict!
  
          .. code-block:: yaml
  
              - mirror:
                - /tmp/vdisk0
                - /tmp/vdisk1
              - /tmp/vdisk2
  
          The above will result in the following zpool create:
  
          .. code-block:: bash
  
              zpool create mypool mirror /tmp/vdisk0 /tmp/vdisk1 /tmp/vdisk2
  
          Creating a 3-way mirror! While you probably expect it to be mirror
          root vdev with 2 devices + a root vdev of 1 device!
  
      '''
      ret = {'name': name,
             'changes': {},
             'result': None,
             'comment': ''}
  
      # config defaults
      default_config = {
          'import': True,
          'import_dirs': None,
          'device_dir': None,
          'force': False
      }
      if __grains__['kernel'] == 'SunOS':
          default_config['device_dir'] = '/dev/dsk'
      elif __grains__['kernel'] == 'Linux':
          default_config['device_dir'] = '/dev'
  
      # merge state config
      if config:
          default_config.update(config)
      config = default_config
  
      # ensure properties are zfs values
      if properties:
          properties = __utils__['zfs.from_auto_dict'](properties)
      elif properties is None:
          properties = {}
      if filesystem_properties:
          filesystem_properties = __utils__['zfs.from_auto_dict'](filesystem_properties)
      elif filesystem_properties is None:
          filesystem_properties = {}
  
      # parse layout
      vdevs = _layout_to_vdev(layout, config['device_dir'])
      if vdevs:
          vdevs.insert(0, name)
  
      # log configuration
      log.debug('zpool.present::%s::config - %s', name, config)
      log.debug('zpool.present::%s::vdevs - %s', name, vdevs)
      log.debug('zpool.present::%s::properties -  %s', name, properties)
      log.debug('zpool.present::%s::filesystem_properties -  %s', name, filesystem_properties)
  
      # ensure the pool is present
      ret['result'] = False
  
      # don't do anything because this is a test
      if __opts__['test']:
          ret['result'] = True
          if __salt__['zpool.exists'](name):
              ret['changes'][name] = 'uptodate'
          else:
              ret['changes'][name] = 'imported' if config['import'] else 'created'
          ret['comment'] = 'storage pool {0} was {1}'.format(name, ret['changes'][name])
  
      # update pool
      elif __salt__['zpool.exists'](name):
          ret['result'] = True
  
          # fetch current pool properties
          properties_current = __salt__['zpool.get'](name, parsable=True)
  
          # build list of properties to update
          properties_update = []
          if properties:
              for prop in properties:
                  # skip unexisting properties
                  if prop not in properties_current:
                      log.warning('zpool.present::%s::update - unknown property: %s', name, prop)
                      continue
  
                  # compare current and wanted value
                  if properties_current[prop] != properties[prop]:
                      properties_update.append(prop)
  
          # update pool properties
          for prop in properties_update:
              res = __salt__['zpool.set'](name, prop, properties[prop])
  
              if 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']:
              ret['comment'] = 'properties updated' if ret['changes'] else 'no update needed'
  
      # import or create the pool (at least try to anyway)
      else:
          # import pool
          if config['import']:
              mod_res = __salt__['zpool.import'](
                  name,
                  force=config['force'],
                  dir=config['import_dirs'],
              )
  
              ret['result'] = mod_res['imported']
              if ret['result']:
                  ret['changes'][name] = 'imported'
                  ret['comment'] = 'storage pool {0} was imported'.format(name)
  
          # create pool
          if not ret['result'] and vdevs:
              log.debug('zpool.present::%s::creating', name)
  
              # execute zpool.create
              mod_res = __salt__['zpool.create'](
                  *vdevs,
                  force=config['force'],
                  properties=properties,
                  filesystem_properties=filesystem_properties
              )
  
              ret['result'] = mod_res['created']
              if ret['result']:
                  ret['changes'][name] = 'created'
                  ret['comment'] = 'storage pool {0} was created'.format(name)
              elif 'error' in mod_res:
                  ret['comment'] = mod_res['error']
              else:
                  ret['comment'] = 'could not create storage pool {0}'.format(name)
  
          # give up, we cannot import the pool and we do not have a layout to create it
          if not ret['result'] and not vdevs:
              ret['comment'] = 'storage pool {0} was not imported, no (valid) layout specified for creation'.format(name)
  
      return ret