parameters: (ctx, config)
docstring: Mount/unmount a ``ceph-fuse`` client.
  
      The config is optional and defaults to mounting on all clients. If
      a config is given, it is expected to be a list of clients to do
      this operation on. This lets you e.g. set up one client with
      ``ceph-fuse`` and another with ``kclient``.
  
      ``brxnet`` should be a Private IPv4 Address range, default range is
      [192.168.0.0/16]
  
      Example that mounts all clients::
  
          tasks:
          - ceph:
          - ceph-fuse:
          - interactive:
          - brxnet: [192.168.0.0/16]
  
      Example that uses both ``kclient` and ``ceph-fuse``::
  
          tasks:
          - ceph:
          - ceph-fuse: [client.0]
          - kclient: [client.1]
          - interactive:
  
      Example that enables valgrind:
  
          tasks:
          - ceph:
          - ceph-fuse:
              client.0:
                valgrind: [--tool=memcheck, --leak-check=full, --show-reachable=yes]
          - interactive:
  
      Example that stops an already-mounted client:
  
      ::
  
          tasks:
              - ceph:
              - ceph-fuse: [client.0]
              - ... do something that requires the FS mounted ...
              - ceph-fuse:
                  client.0:
                      mounted: false
              - ... do something that requires the FS unmounted ...
  
      Example that adds more generous wait time for mount (for virtual machines):
  
          tasks:
          - ceph:
          - ceph-fuse:
              client.0:
                mount_wait: 60 # default is 0, do not wait before checking /sys/
                mount_timeout: 120 # default is 30, give up if /sys/ is not populated
          - interactive:
  
      :param ctx: Context
      :param config: Configuration
docstring_summary: Mount/unmount a ``ceph-fuse`` client.
docstring_tokens: Mount / unmount a ceph - fuse client .
function: def task(ctx, config):
      """
      Mount/unmount a ``ceph-fuse`` client.
  
      The config is optional and defaults to mounting on all clients. If
      a config is given, it is expected to be a list of clients to do
      this operation on. This lets you e.g. set up one client with
      ``ceph-fuse`` and another with ``kclient``.
  
      ``brxnet`` should be a Private IPv4 Address range, default range is
      [192.168.0.0/16]
  
      Example that mounts all clients::
  
          tasks:
          - ceph:
          - ceph-fuse:
          - interactive:
          - brxnet: [192.168.0.0/16]
  
      Example that uses both ``kclient` and ``ceph-fuse``::
  
          tasks:
          - ceph:
          - ceph-fuse: [client.0]
          - kclient: [client.1]
          - interactive:
  
      Example that enables valgrind:
  
          tasks:
          - ceph:
          - ceph-fuse:
              client.0:
                valgrind: [--tool=memcheck, --leak-check=full, --show-reachable=yes]
          - interactive:
  
      Example that stops an already-mounted client:
  
      ::
  
          tasks:
              - ceph:
              - ceph-fuse: [client.0]
              - ... do something that requires the FS mounted ...
              - ceph-fuse:
                  client.0:
                      mounted: false
              - ... do something that requires the FS unmounted ...
  
      Example that adds more generous wait time for mount (for virtual machines):
  
          tasks:
          - ceph:
          - ceph-fuse:
              client.0:
                mount_wait: 60 # default is 0, do not wait before checking /sys/
                mount_timeout: 120 # default is 30, give up if /sys/ is not populated
          - interactive:
  
      :param ctx: Context
      :param config: Configuration
      """
      log.info('Running ceph_fuse task...')
  
      if config is None:
          ids = misc.all_roles_of_type(ctx.cluster, 'client')
          client_roles = [f'client.{id_}' for id_ in ids]
          config = dict([r, dict()] for r in client_roles)
      elif isinstance(config, list):
          client_roles = config
          config = dict([r, dict()] for r in client_roles)
      elif isinstance(config, dict):
          client_roles = filter(lambda x: 'client.' in x, config.keys())
      else:
          raise ValueError(f"Invalid config object: {config} ({config.__class__})")
      log.info(f"config is {config}")
  
      clients = list(misc.get_clients(ctx=ctx, roles=client_roles))
      testdir = misc.get_testdir(ctx)
      all_mounts = getattr(ctx, 'mounts', {})
      mounted_by_me = {}
      skipped = {}
      remotes = set()
  
      brxnet = config.get("brxnet", None)
  
      # Construct any new FuseMount instances
      overrides = ctx.config.get('overrides', {}).get('ceph-fuse', {})
      top_overrides = dict(filter(lambda x: 'client.' not in x[0], overrides.items()))
      for id_, remote in clients:
          entity = f"client.{id_}"
          client_config = config.get(entity)
          if client_config is None:
              client_config = {}
          # top level overrides
          misc.deep_merge(client_config, top_overrides)
          # mount specific overrides
          client_config_overrides = overrides.get(entity)
          misc.deep_merge(client_config, client_config_overrides)
          log.info(f"{entity} config is {client_config}")
  
          remotes.add(remote)
          auth_id = client_config.get("auth_id", id_)
          cephfs_name = client_config.get("cephfs_name")
  
          skip = client_config.get("skip", False)
          if skip:
              skipped[id_] = skip
              continue
  
          if id_ not in all_mounts:
              fuse_mount = FuseMount(ctx=ctx, client_config=client_config,
                                     test_dir=testdir, client_id=auth_id,
                                     client_remote=remote, brxnet=brxnet,
                                     cephfs_name=cephfs_name)
              all_mounts[id_] = fuse_mount
          else:
              # Catch bad configs where someone has e.g. tried to use ceph-fuse and kcephfs for the same client
              assert isinstance(all_mounts[id_], FuseMount)
  
          if not config.get("disabled", False) and client_config.get('mounted', True):
              mounted_by_me[id_] = {"config": client_config, "mount": all_mounts[id_]}
  
      ctx.mounts = all_mounts
  
      # Umount any pre-existing clients that we have not been asked to mount
      for client_id in set(all_mounts.keys()) - set(mounted_by_me.keys()) - set(skipped.keys()):
          mount = all_mounts[client_id]
          if mount.is_mounted():
              mount.umount_wait()
  
      for remote in remotes:
          FuseMount.cleanup_stale_netnses_and_bridge(remote)
  
      # Mount any clients we have been asked to (default to mount all)
      log.info('Mounting ceph-fuse clients...')
      for info in mounted_by_me.values():
          config = info["config"]
          mount_x = info['mount']
          if config.get("mount_path"):
              mount_x.cephfs_mntpt = config.get("mount_path")
          if config.get("mountpoint"):
              mount_x.hostfs_mntpt = config.get("mountpoint")
          mount_x.mount()
  
      for info in mounted_by_me.values():
          info["mount"].wait_until_mounted()
  
      try:
          yield all_mounts
      finally:
          log.info('Unmounting ceph-fuse clients...')
  
          for info in mounted_by_me.values():
              # Conditional because an inner context might have umounted it
              mount = info["mount"]
              if mount.is_mounted():
                  mount.umount_wait()
          for remote in remotes:
              FuseMount.cleanup_stale_netnses_and_bridge(remote)
function_tokens: def task ( ctx , config ) : log . info ( 'Running ceph_fuse task...' ) if config is None : ids = misc . all_roles_of_type ( ctx . cluster , 'client' ) client_roles = [ f'client.{id_}' for id_ in ids ] config = dict ( [ r , dict ( ) ] for r in client_roles ) elif isinstance ( config , list ) : client_roles = config config = dict ( [ r , dict ( ) ] for r in client_roles ) elif isinstance ( config , dict ) : client_roles = filter ( lambda x : 'client.' in x , config . keys ( ) ) else : raise ValueError ( f"Invalid config object: {config} ({config.__class__})" ) log . info ( f"config is {config}" ) clients = list ( misc . get_clients ( ctx = ctx , roles = client_roles ) ) testdir = misc . get_testdir ( ctx ) all_mounts = getattr ( ctx , 'mounts' , { } ) mounted_by_me = { } skipped = { } remotes = set ( ) brxnet = config . get ( "brxnet" , None ) # Construct any new FuseMount instances overrides = ctx . config . get ( 'overrides' , { } ) . get ( 'ceph-fuse' , { } ) top_overrides = dict ( filter ( lambda x : 'client.' not in x [ 0 ] , overrides . items ( ) ) ) for id_ , remote in clients : entity = f"client.{id_}" client_config = config . get ( entity ) if client_config is None : client_config = { } # top level overrides misc . deep_merge ( client_config , top_overrides ) # mount specific overrides client_config_overrides = overrides . get ( entity ) misc . deep_merge ( client_config , client_config_overrides ) log . info ( f"{entity} config is {client_config}" ) remotes . add ( remote ) auth_id = client_config . get ( "auth_id" , id_ ) cephfs_name = client_config . get ( "cephfs_name" ) skip = client_config . get ( "skip" , False ) if skip : skipped [ id_ ] = skip continue if id_ not in all_mounts : fuse_mount = FuseMount ( ctx = ctx , client_config = client_config , test_dir = testdir , client_id = auth_id , client_remote = remote , brxnet = brxnet , cephfs_name = cephfs_name ) all_mounts [ id_ ] = fuse_mount else : # Catch bad configs where someone has e.g. tried to use ceph-fuse and kcephfs for the same client assert isinstance ( all_mounts [ id_ ] , FuseMount ) if not config . get ( "disabled" , False ) and client_config . get ( 'mounted' , True ) : mounted_by_me [ id_ ] = { "config" : client_config , "mount" : all_mounts [ id_ ] } ctx . mounts = all_mounts # Umount any pre-existing clients that we have not been asked to mount for client_id in set ( all_mounts . keys ( ) ) - set ( mounted_by_me . keys ( ) ) - set ( skipped . keys ( ) ) : mount = all_mounts [ client_id ] if mount . is_mounted ( ) : mount . umount_wait ( ) for remote in remotes : FuseMount . cleanup_stale_netnses_and_bridge ( remote ) # Mount any clients we have been asked to (default to mount all) log . info ( 'Mounting ceph-fuse clients...' ) for info in mounted_by_me . values ( ) : config = info [ "config" ] mount_x = info [ 'mount' ] if config . get ( "mount_path" ) : mount_x . cephfs_mntpt = config . get ( "mount_path" ) if config . get ( "mountpoint" ) : mount_x . hostfs_mntpt = config . get ( "mountpoint" ) mount_x . mount ( ) for info in mounted_by_me . values ( ) : info [ "mount" ] . wait_until_mounted ( ) try : yield all_mounts finally : log . info ( 'Unmounting ceph-fuse clients...' ) for info in mounted_by_me . values ( ) : # Conditional because an inner context might have umounted it mount = info [ "mount" ] if mount . is_mounted ( ) : mount . umount_wait ( ) for remote in remotes : FuseMount . cleanup_stale_netnses_and_bridge ( remote )