]> git-server-git.apps.pok.os.sepia.ceph.com Git - teuthology.git/commitdiff
Added docstrings, and improved some of the comments on several tasks. 144/head
authorWarren Usui <warren.usui@inktank.com>
Sat, 12 Oct 2013 08:28:27 +0000 (01:28 -0700)
committerWarren Usui <warren.usui@inktank.com>
Sat, 12 Oct 2013 08:35:34 +0000 (01:35 -0700)
59 files changed:
teuthology/task/admin_socket.py
teuthology/task/autotest.py
teuthology/task/ceph-deploy.py
teuthology/task/ceph-fuse.py
teuthology/task/ceph.py
teuthology/task/ceph_client.py
teuthology/task/chef.py
teuthology/task/cifs-mount.py
teuthology/task/clock.py
teuthology/task/cram.py
teuthology/task/die_on_err.py
teuthology/task/divergent_priors.py
teuthology/task/dump_stuck.py
teuthology/task/exec.py
teuthology/task/filestore_idempotent.py
teuthology/task/interactive.py
teuthology/task/kclient.py
teuthology/task/kcon_most.py
teuthology/task/kernel.py
teuthology/task/knfsd.py
teuthology/task/localdir.py
teuthology/task/lockfile.py
teuthology/task/locktest.py
teuthology/task/lost_unfound.py
teuthology/task/manypools.py
teuthology/task/mds_thrash.py
teuthology/task/mon_recovery.py
teuthology/task/mpi.py
teuthology/task/multibench.py
teuthology/task/nfs.py
teuthology/task/nop.py
teuthology/task/object_source_down.py
teuthology/task/omapbench.py
teuthology/task/osd_backfill.py
teuthology/task/osd_failsafe_enospc.py
teuthology/task/osd_recovery.py
teuthology/task/parallel.py
teuthology/task/parallel_example.py
teuthology/task/peer.py
teuthology/task/pexec.py
teuthology/task/qemu.py
teuthology/task/rados.py
teuthology/task/radosbench.py
teuthology/task/radosgw-admin.py
teuthology/task/radosgw-agent.py
teuthology/task/rbd.py
teuthology/task/rbd_fsx.py
teuthology/task/rest-api.py
teuthology/task/restart.py
teuthology/task/samba.py
teuthology/task/scrub.py
teuthology/task/scrub_test.py
teuthology/task/sequential.py
teuthology/task/sleep.py
teuthology/task/tasktest.py
teuthology/task/thrashosds.py
teuthology/task/timer.py
teuthology/task/watch_notify_stress.py
teuthology/task/workunit.py

index dbb7a17cefcc5b599735bdfbe02b679cbae9b058..20a670122a9b68f0f17a4082170e15d587382218 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Admin Socket task -- used in rados, powercycle, and smoke testing
+"""
 from cStringIO import StringIO
 
 import json
@@ -11,6 +14,7 @@ from teuthology.parallel import parallel
 
 log = logging.getLogger(__name__)
 
+
 def task(ctx, config):
     """
     Run an admin socket command, make sure the output is json, and run
@@ -54,18 +58,30 @@ def task(ctx, config):
     Note that there must be a ceph client with an admin socket running
     before this task is run. The tests are parallelized at the client
     level. Tests for a single client are run serially.
+
+    :param ctx: Context
+    :param config: Configuration
     """
     assert isinstance(config, dict), \
         'admin_socket task requires a dict for configuration'
     teuthology.replace_all_with_clients(ctx.cluster, config)
 
-    with parallel() as p:
+    with parallel() as ptask:
         for client, tests in config.iteritems():
-            p.spawn(_run_tests, ctx, client, tests)
+            ptask.spawn(_run_tests, ctx, client, tests)
+
 
 def _socket_command(ctx, remote, socket_path, command, args):
     """
     Run an admin socket command and return the result as a string.
+
+    :param ctx: Context
+    :param remote: Remote site
+    :param socket_path: path to socket
+    :param command: command to be run remotely
+    :param args: command arguments
+
+    :returns: output of command in json format
     """
     json_fp = StringIO()
     testdir = teuthology.get_testdir(ctx)
@@ -87,7 +103,8 @@ def _socket_command(ctx, remote, socket_path, command, args):
             break
         assert max_tries > 0
         max_tries -= 1
-        log.info('ceph cli returned an error, command not registered yet?  sleeping and retrying ...')
+        log.info('ceph cli returned an error, command not registered yet?')
+        log.info('sleeping and retrying ...')
         time.sleep(1)
     out = json_fp.getvalue()
     json_fp.close()
@@ -95,6 +112,15 @@ def _socket_command(ctx, remote, socket_path, command, args):
     return json.loads(out)
 
 def _run_tests(ctx, client, tests):
+    """
+    Create a temp directory and wait for a client socket to be created.
+    For each test, copy the executable locally and run the test.
+    Remove temp directory when finished.
+
+    :param ctx: Context
+    :param client: client machine to run the test
+    :param tests: list of tests to run
+    """
     testdir = teuthology.get_testdir(ctx)
     log.debug('Running admin socket tests on %s', client)
     (remote,) = ctx.cluster.only(client).remotes.iterkeys()
@@ -164,4 +190,3 @@ def _run_tests(ctx, client, tests):
                 'rm', '-rf', '--', tmp_dir,
                 ],
             )
-
index d1b22c6a4fd9c7df1bdabcf9020a97d220578855..24a7675df277ff10f99271029f4edc114916375e 100644 (file)
@@ -1,3 +1,6 @@
+""" 
+Run an autotest test on the ceph cluster.
+"""
 import json
 import logging
 import os
@@ -70,6 +73,9 @@ def task(ctx, config):
             p.spawn(_run_tests, testdir, remote, role, tests)
 
 def _download(testdir, remote):
+    """
+    Download.  Does not explicitly support muliple tasks in a single run.
+    """
     remote.run(
         args=[
             # explicitly does not support multiple autotest tasks
@@ -94,6 +100,9 @@ def _download(testdir, remote):
         )
 
 def _run_tests(testdir, remote, role, tests):
+    """
+    Spawned to run test on remote site
+    """
     assert isinstance(role, basestring)
     PREFIX = 'client.'
     assert role.startswith(PREFIX)
index 1e6427162debb2f176214122a51bb36e13b7b68b..7ada79f7402aeda0e60777e509d4d7aab7f7dd16 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Execute ceph-deploy as a task
+"""
 from cStringIO import StringIO
 
 import contextlib
@@ -82,6 +85,7 @@ def is_healthy(ctx, config):
         time.sleep(1)
 
 def get_nodes_using_roles(ctx, config, role):
+    """Extract the names of nodes that match a given role from a cluster"""
     newl = []
     for _remote, roles_for_host in ctx.cluster.remotes.iteritems():
         for id_ in teuthology.roles_of_type(roles_for_host, role):
@@ -95,6 +99,7 @@ def get_nodes_using_roles(ctx, config, role):
     return newl
 
 def get_dev_for_osd(ctx, config):
+    """Get a list of all osd device names."""
     osd_devs = []
     for remote, roles_for_host in ctx.cluster.remotes.iteritems():
         host = remote.name.split('@')[-1]
@@ -109,6 +114,7 @@ def get_dev_for_osd(ctx, config):
     return osd_devs
 
 def get_all_nodes(ctx, config):
+    """Return a string of node names separated by blanks"""
     nodelist = []
     for t, k in ctx.config['targets'].iteritems():
         host = t.split('@')[-1]
@@ -118,6 +124,7 @@ def get_all_nodes(ctx, config):
     return nodelist
 
 def execute_ceph_deploy(ctx, config, cmd):
+    """Remotely execute a ceph_deploy command"""
     testdir = teuthology.get_testdir(ctx)
     ceph_admin = teuthology.get_first_mon(ctx, config)
     exec_cmd = cmd
@@ -136,6 +143,7 @@ def execute_ceph_deploy(ctx, config, cmd):
 
 @contextlib.contextmanager
 def build_ceph_cluster(ctx, config):
+    """Build a ceph cluster"""
     log.info('Building ceph cluster using ceph-deploy...')
     testdir = teuthology.get_testdir(ctx)
     ceph_branch = None
@@ -178,12 +186,12 @@ def build_ceph_cluster(ctx, config):
     if config.get('conf') is not None:
         confp = config.get('conf')
         for section, keys in confp.iteritems():
-                lines = '[{section}]\n'.format(section=section)
+            lines = '[{section}]\n'.format(section=section)
+            teuthology.append_lines_to_file(remote, conf_path, lines, sudo=True)
+            for key, value in keys.iteritems():
+                log.info("[%s] %s = %s" % (section, key, value))
+                lines = '{key} = {value}\n'.format(key=key, value=value)
                 teuthology.append_lines_to_file(remote, conf_path, lines, sudo=True)
-                for key, value in keys.iteritems():
-                    log.info("[%s] %s = %s" % (section, key, value))
-                    lines = '{key} = {value}\n'.format(key=key, value=value)
-                    teuthology.append_lines_to_file(remote, conf_path, lines, sudo=True)
 
     estatus_install = execute_ceph_deploy(ctx, config, install_nodes)
     if estatus_install != 0:
index eeff1c0e285411863adb3fde6dabe031b5bfada2..6031313a45523ca51f2a8847a13da22fa0bf5fd8 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Ceph FUSE client task
+"""
 import contextlib
 import logging
 import os
@@ -41,6 +44,8 @@ def task(ctx, config):
               valgrind: [--tool=memcheck, --leak-check=full, --show-reachable=yes]
         - interactive:
 
+    :param ctx: Context
+    :param config: Configuration
     """
     log.info('Mounting ceph-fuse clients...')
     fuse_daemons = {}
index 2337b0e6443f6bd6d69f388c8a1f43c1ea8d9bd6..dcab9731033aa568e7ad6eddfb7e78aeed4fe438 100644 (file)
@@ -1,3 +1,8 @@
+"""
+Ceph cluster task.   
+
+Handle the setup, starting, and clean-up of a Ceph cluster.
+"""
 from cStringIO import StringIO
 
 import argparse
@@ -14,7 +19,19 @@ import ceph_client as cclient
 log = logging.getLogger(__name__)
 
 class DaemonState(object):
+    """
+    Daemon State.  A daemon exists for each instance of each role.
+    """
     def __init__(self, remote, role, id_, *command_args, **command_kwargs):
+        """
+        Pass remote command information as parameters to remote site
+
+        :param remote: Remote site
+        :param role: Role (osd, rgw, mon, mds)
+        :param id_: Id within role (osd.1, osd.2, for eaxmple)
+        :param command_args: positional arguments (used in restart commands)
+        :param command_kwargs: keyword arguments (used in restart commands)
+        """
         self.remote = remote
         self.command_args = command_args
         self.command_kwargs = command_kwargs
@@ -25,6 +42,8 @@ class DaemonState(object):
 
     def stop(self):
         """
+        Stop this daemon instance.
+
         Note: this can raise a run.CommandFailedError,
         run.CommandCrashedError, or run.ConnectionLostError.
         """
@@ -38,6 +57,12 @@ class DaemonState(object):
         self.log.info('Stopped')
 
     def restart(self, *args, **kwargs):
+        """
+        Restart with a new command passed in the arguments
+
+        :param args: positional arguments passed to remote.run
+        :param kwargs: keyword arguments passed to remote.run
+        """ 
         self.log.info('Restarting')
         if self.proc is not None:
             self.log.debug('stopping old one...')
@@ -50,6 +75,11 @@ class DaemonState(object):
         self.log.info('Started')
 
     def restart_with_args(self, extra_args):
+        """
+        Restart, adding new paramaters to the current command.
+        
+        :param extra_args: Extra keyword arguments to be added.
+        """
         self.log.info('Restarting')
         if self.proc is not None:
             self.log.debug('stopping old one...')
@@ -65,25 +95,57 @@ class DaemonState(object):
         self.log.info('Started')
 
     def signal(self, sig):
+        """
+        Send a signal to associated remote commnad
+
+        :param sig: signal to send
+        """
         self.proc.stdin.write(struct.pack('!b', sig))
         self.log.info('Sent signal %d', sig)
 
     def running(self):
+        """
+        Are we running?
+        :return: True if remote run command value is set, False otherwise. 
+        """
         return self.proc is not None
 
     def reset(self):
+        """
+        clear remote run command value.
+        """
         self.proc = None
 
     def wait_for_exit(self):
+        """
+        clear remote run command value after waiting for exit.
+        """
         if self.proc:
             run.wait([self.proc])
             self.proc = None
 
 class CephState(object):
+    """
+    Collection of daemon state instances
+    """
     def __init__(self):
+        """
+        self.daemons is a dictionary indexed by role.  Each entry is a dictionary of
+        DaemonState values indexcd by an id parameter.
+        """
         self.daemons = {}
 
     def add_daemon(self, remote, role, id_, *args, **kwargs):
+        """
+        Add a daemon.  If there already is a daemon for this id_ and role, stop that
+        daemon and.  Restart the damon once the new value is set.
+        
+        :param remote: Remote site
+        :param role: Role (osd, mds, mon, rgw,  for example)
+        :param id_: Id (index into role dictionary)
+        :param args: Daemonstate positional parameters
+        :param kwargs: Daemonstate keyword parameters
+        """
         if role not in self.daemons:
             self.daemons[role] = {}
         if id_ in self.daemons[role]:
@@ -93,16 +155,35 @@ class CephState(object):
         self.daemons[role][id_].restart()
 
     def get_daemon(self, role, id_):
+        """
+        get the daemon associated with this id_ for this role.
+
+        :param role: Role (osd, mds, mon, rgw,  for example)
+        :param id_: Id (index into role dictionary)
+        """
         if role not in self.daemons:
             return None
         return self.daemons[role].get(str(id_), None)
 
     def iter_daemons_of_role(self, role):
+        """
+        Iterate through all daemon instances for this role.  Return dictionary of
+        daemon values.
+
+        :param role: Role (osd, mds, mon, rgw,  for example)
+        """
         return self.daemons.get(role, {}).values()
 
 
 @contextlib.contextmanager
 def ceph_log(ctx, config):
+    """
+    Create /var/log/ceph log directory that is open to everyone.
+    Add valgrind and profiling-logger directories.
+
+    :param ctx: Context
+    :param config: Configuration
+    """
     log.info('Making ceph log dir writeable by non-root...')
     run.wait(
         ctx.cluster.run(
@@ -148,6 +229,14 @@ def ceph_log(ctx, config):
 
 @contextlib.contextmanager
 def ship_utilities(ctx, config):
+    """
+    Write a copy of valgrind.supp to each of the remote sites.  Set executables used
+    by Ceph in /usr/local/bin.  When finished (upon exit of the teuthology run), remove
+    these files.
+
+    :param ctx: Context
+    :param config: Configuration
+    """
     assert config is None
     testdir = teuthology.get_testdir(ctx)
     filenames = []
@@ -207,10 +296,25 @@ def ship_utilities(ctx, config):
 
 
 def assign_devs(roles, devs):
+    """
+    Create a dictionary of devs indexed by roles
+
+    :param roles: List of roles 
+    :param devs: Corresponding list of devices.
+    :returns: Dictionary of devs indexed by roles.
+    """
     return dict(zip(roles, devs))
 
 @contextlib.contextmanager
 def valgrind_post(ctx, config):
+    """
+    After the tests run, look throught all the valgrind logs.  Exceptions are raised
+    if textual errors occured in the logs, or if valgrind exceptions were detected in
+    the logs.
+
+    :param ctx: Context
+    :param config: Configuration
+    """
     try:
         yield
     finally:
@@ -259,6 +363,13 @@ def valgrind_post(ctx, config):
 
 
 def mount_osd_data(ctx, remote, osd):
+    """
+    Mount a remote OSD
+    
+    :param ctx: Context
+    :param remote: Remote site
+    :param ods: Osd name
+    """
     log.debug('Mounting data for osd.{o} on {r}'.format(o=osd, r=remote))
     if remote in ctx.disk_config.remote_to_roles_to_dev and osd in ctx.disk_config.remote_to_roles_to_dev[remote]:
         dev = ctx.disk_config.remote_to_roles_to_dev[remote][osd]
@@ -281,6 +392,12 @@ def mount_osd_data(ctx, remote, osd):
             )
 
 def make_admin_daemon_dir(ctx, remote):
+    """
+    Create /var/run/ceph directory on remote site.
+
+    :param ctx: Context
+    :param remote: Remote site
+    """
     remote.run(
             args=[
                 'sudo',
@@ -290,6 +407,29 @@ def make_admin_daemon_dir(ctx, remote):
 
 @contextlib.contextmanager
 def cluster(ctx, config):
+    """
+    Handle the creation and removal of a ceph cluster.
+
+    On startup:
+        Create directories needed for the cluster.
+        Create remote journals for all osds.
+        Create and set keyring.
+        Copy the monmap to tht test systems.
+        Setup mon nodes.
+        Setup mds nodes.
+        Mkfs osd nodes.
+        Add keyring information to monmaps
+        Mkfs mon nodes.
+         
+    On exit:
+        If errors occured, extract a failure message and store in ctx.summary.
+        Unmount all test files and temporary journaling files.
+        Save the monitor information and archive all ceph logs.
+        Cleanup the keyring setup, and remove all monitor map and data files left over.
+
+    :param ctx: Context
+    :param config: Configuration
+    """
     testdir = teuthology.get_testdir(ctx)
     log.info('Creating ceph cluster...')
     run.wait(
@@ -747,6 +887,14 @@ def cluster(ctx, config):
 
         log.info('Checking cluster log for badness...')
         def first_in_ceph_log(pattern, excludes):
+            """
+            Find the first occurence of the pattern specified in the Ceph log,
+            Returns None if none found.  
+            
+            :param pattern: Pattern scanned for.
+            :param excludes: Patterns to ignore.
+            :return: First line of text (or None if not found)
+            """
             args = [
                 'sudo',
                 'egrep', pattern,
@@ -871,6 +1019,16 @@ def cluster(ctx, config):
 
 @contextlib.contextmanager
 def run_daemon(ctx, config, type_):
+    """
+    Run daemons for a role type.  Handle the startup and termination of a a daemon.
+    On startup -- set coverages, cpu_profile, valgrind values for all remotes,
+    and a max_mds value for one mds.
+    On cleanup -- Stop all existing daemons of this type.
+
+    :param ctx: Context
+    :param config: Configuration
+    :paran type_: Role type
+    """
     log.info('Starting %s daemons...' % type_)
     testdir = teuthology.get_testdir(ctx)
     daemons = ctx.cluster.only(teuthology.is_type(type_))
@@ -941,6 +1099,12 @@ def run_daemon(ctx, config, type_):
         teuthology.stop_daemons_of_type(ctx, type_)
 
 def healthy(ctx, config):
+    """
+    Wait for all osd's to be up, and for the ceph health monitor to return HEALTH_OK.
+
+    :param ctx: Context
+    :param config: Configuration
+    """
     log.info('Waiting until ceph is healthy...')
     firstmon = teuthology.get_first_mon(ctx, config)
     (mon0_remote,) = ctx.cluster.only(firstmon).remotes.keys()
@@ -955,6 +1119,12 @@ def healthy(ctx, config):
         )
 
 def wait_for_osds_up(ctx, config):
+    """
+    Wait for all osd's to come up.
+
+    :param ctx: Context
+    :param config: Configuration
+    """
     log.info('Waiting until ceph osds are all up...')
     firstmon = teuthology.get_first_mon(ctx, config)
     (mon0_remote,) = ctx.cluster.only(firstmon).remotes.keys()
@@ -965,6 +1135,12 @@ def wait_for_osds_up(ctx, config):
         )
 
 def wait_for_mon_quorum(ctx, config):
+    """
+    Check renote ceph status until all monitors are up.
+
+    :param ctx: Context
+    :param config: Configuration
+    """
     import json
     import time
 
@@ -990,7 +1166,7 @@ def wait_for_mon_quorum(ctx, config):
 
 @contextlib.contextmanager
 def restart(ctx, config):
-   """
+    """
    restart ceph daemons
 
    For example::
@@ -1009,32 +1185,34 @@ def restart(ctx, config):
           wait-for-healthy: false
           wait-for-osds-up: true
 
-   """
-   if config is None:
-       config = {}
-   if isinstance(config, list):
-       config = { 'daemons': config }
-   if 'daemons' not in config:
-       config['daemons'] = []
-       type_daemon = ['mon', 'osd', 'mds', 'rgw']
-       for d in type_daemon:
-           type_ = d
-           for daemon in ctx.daemons.iter_daemons_of_role(type_):
-               config['daemons'].append(type_ + '.' + daemon.id_)
-
-   assert isinstance(config['daemons'], list)
-   daemons = dict.fromkeys(config['daemons'])
-   for i in daemons.keys():
-       type_ = i.split('.', 1)[0]
-       id_ = i.split('.', 1)[1]
-       ctx.daemons.get_daemon(type_, id_).stop()
-       ctx.daemons.get_daemon(type_, id_).restart()
-
-   if config.get('wait-for-healthy', True):
-       healthy(ctx=ctx, config=None)
-   if config.get('wait-for-osds-up', False):
-       wait_for_osds_up(ctx=ctx, config=None)
-   yield
+    :param ctx: Context
+    :param config: Configuration
+    """
+    if config is None:
+        config = {}
+    if isinstance(config, list):
+        config = { 'daemons': config }
+    if 'daemons' not in config:
+        config['daemons'] = []
+        type_daemon = ['mon', 'osd', 'mds', 'rgw']
+        for d in type_daemon:
+            type_ = d
+            for daemon in ctx.daemons.iter_daemons_of_role(type_):
+                config['daemons'].append(type_ + '.' + daemon.id_)
+
+    assert isinstance(config['daemons'], list)
+    daemons = dict.fromkeys(config['daemons'])
+    for i in daemons.keys():
+        type_ = i.split('.', 1)[0]
+        id_ = i.split('.', 1)[1]
+        ctx.daemons.get_daemon(type_, id_).stop()
+        ctx.daemons.get_daemon(type_, id_).restart()
+
+    if config.get('wait-for-healthy', True):
+        healthy(ctx=ctx, config=None)
+    if config.get('wait-for-osds-up', False):
+        wait_for_osds_up(ctx=ctx, config=None)
+    yield
 
 @contextlib.contextmanager
 def task(ctx, config):
@@ -1128,6 +1306,8 @@ def task(ctx, config):
         - ceph:
             log-whitelist: ['foo.*bar', 'bad message']
 
+    :param ctx: Context
+    :param config: Configuration
     """
     if config is None:
         config = {}
index e2ee59dcaf02e579889b06e511eeb7d680f2e196..8935fc871930438e25530bfeb1b443059dd9cd54 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Set up client keyring
+"""
 import logging
 
 from teuthology import misc as teuthology
@@ -6,6 +9,9 @@ from ..orchestra import run
 log = logging.getLogger(__name__)
 
 def create_keyring(ctx):
+    """
+    Set up key ring on remote sites
+    """
     log.info('Setting up client nodes...')
     clients = ctx.cluster.only(teuthology.is_type('client'))
     testdir = teuthology.get_testdir(ctx)
index e32bb4b1857bc277cf8879b2a882cc2be2ca53be..db793c3939070d9b54aa98940b34bec96fcec492 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Chef-solo task
+"""
 import logging
 
 from ..orchestra import run
index 179738d1fea8a714dcdae264477dd75dbeb0f09a..ac58f31cc0a28029bdf016a7b4c7103879d3fcc8 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Mount cifs clients.  Unmount when finished.
+"""
 import contextlib
 import logging
 import os
@@ -44,6 +47,9 @@ def task(ctx, config):
         - cifs-mount:
             client.0:
                 share: cephfuse
+
+    :param ctx: Context
+    :param config: Configuration
     """
     log.info('Mounting cifs clients...')
 
@@ -58,7 +64,7 @@ def task(ctx, config):
     from teuthology.task.samba import get_sambas
     samba_roles = ['samba.{id_}'.format(id_=id_) for id_ in teuthology.all_roles_of_type(ctx.cluster, 'samba')]
     sambas = list(get_sambas(ctx=ctx, roles=samba_roles))
-    (ip, port) = sambas[0][1].ssh.get_transport().getpeername()
+    (ip, _) = sambas[0][1].ssh.get_transport().getpeername()
     log.info('samba ip: {ip}'.format(ip=ip))
 
     for id_, remote in clients:
index 15ebf1bdb6c59291a9c1906b00cba20e7af7447d..d7a26c42cbcc497c6ff7c008ddbfd882eb8c0b96 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Clock synchronizer 
+"""
 import logging
 import contextlib
 
@@ -22,6 +25,8 @@ def task(ctx, config):
 
     to sync.
 
+    :param ctx: Context
+    :param config: Configuration
     """
 
     log.info('Syncing clocks and checking initial clock skew...')
@@ -68,6 +73,12 @@ def task(ctx, config):
 
 @contextlib.contextmanager
 def check(ctx, config):
+    """
+    Run ntpdc at the start and the end of the task.
+   
+    :param ctx: Context
+    :param config: Configuration
+    """
     log.info('Checking initial clock skew...')
     for rem in ctx.cluster.remotes.iterkeys():
         rem.run(
index 64358d5105e88170fee9142065caa286e0e0b58a..05824d26ab0e6bd60bf0442d4edd740d7ac8acaa 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Cram tests
+"""
 import logging
 import os
 
@@ -34,6 +37,9 @@ def task(ctx, config):
         - cram:
             clients:
               all: [http://ceph.com/qa/test.t]
+
+    :param ctx: Context
+    :param config: Configuration
     """
     assert isinstance(config, dict)
     assert 'clients' in config and isinstance(config['clients'], dict), \
@@ -99,6 +105,12 @@ def task(ctx, config):
                 )
 
 def _run_tests(ctx, role):
+    """
+    For each role, check to make sure it's a client, then run the cram on that client
+
+    :param ctx: Context
+    :param role: Roles
+    """
     assert isinstance(role, basestring)
     PREFIX = 'client.'
     assert role.startswith(PREFIX)
index 959f4b6b99e30f14c1880ba15a59b9832937a6fe..1dfd37073628de17a321061bac832c975820e63b 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Raise exceptions on osd coredumps or test err directories
+"""
 import contextlib
 import logging
 import time
index 18aca5b579edf9c4360d43d3faa8657e35721d82..432614f233cb1f879209b097e1cca1c4b2357c79 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Special case divergence test
+"""
 import logging
 import time
 
index f86feb41806b3c129f776b0a803109d17edd9305..9e1780f01565a51223ed53cd0e8a9467fe9b4d0e 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Dump_stuck command
+"""
 import logging
 import re
 import time
@@ -9,6 +12,17 @@ from teuthology import misc as teuthology
 log = logging.getLogger(__name__)
 
 def check_stuck(manager, num_inactive, num_unclean, num_stale, timeout=10):
+    """
+    Do checks.  Make sure get_stuck_pgs return the right amout of information, then
+    extract health information from the raw_cluster_cmd and compare the results with
+    values passed in.  This passes if all asserts pass.
+    :param num_manager: Ceph manager
+    :param num_inactive: number of inaactive pages that are stuck
+    :param num_unclean: number of unclean pages that are stuck
+    :paran num_stale: number of stale pages that are stuck
+    :param timeout: timeout value for get_stuck_pgs calls
+    """
     inactive = manager.get_stuck_pgs('inactive', timeout)
     assert len(inactive) == num_inactive
     unclean = manager.get_stuck_pgs('unclean', timeout)
@@ -33,6 +47,8 @@ def task(ctx, config):
     """
     Test the dump_stuck command.
 
+    :param ctx: Context
+    :param config: Configuration
     """
     assert config is None, \
         'dump_stuck requires no configuration'
index 4d384fcb6965d6969206439bb27c2ba02c8bd512..f951f77a8a379a2e7c798484d97c6a2e12562155 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Exececute custom commands
+"""
 import logging
 
 from teuthology import misc as teuthology
@@ -17,6 +20,8 @@ def task(ctx, config):
               - echo 'module ceph +p' > /sys/kernel/debug/dynamic_debug/control
         - interactive:
 
+    :param ctx: Context
+    :param config: Configuration
     """
     log.info('Executing custom commands...')
     assert isinstance(config, dict), "task exec got invalid config"
index fea790a765ceb533ec90f2491d7b4eec284308f4..317e9a56fd0c61d002f0b39c8300e0d928e04ba6 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Filestore/filejournal handler
+"""
 import logging
 from ..orchestra import run
 import random
@@ -12,6 +15,9 @@ def task(ctx, config):
 
     Currently this is a kludge; we require the ceph task preceeds us just
     so that we get the tarball installed to run the test binary.
+
+    :param ctx: Context
+    :param config: Configuration
     """
     assert config is None or isinstance(config, list) \
         or isinstance(config, dict), \
index debbf51fbe7eda1000f0a1b64f5a76b852dc7b42..c0aa7e0a11687c99069b45a51ed1584cb690ad2a 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Drop into a python shell
+"""
 import code
 import readline
 import rlcompleter
index 9fcec524d9cd98718222bb9788f9eb065c0cdf45..2229fe07ea1d571208e160c9bd6863ca3ff691bf 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Mount/unmount a ``kernel`` client.
+"""
 import contextlib
 import logging
 import os
@@ -30,6 +33,9 @@ def task(ctx, config):
         - ceph-fuse: [client.0]
         - kclient: [client.1]
         - interactive:
+
+    :param ctx: Context
+    :param config: Configuration
     """
     log.info('Mounting kernel clients...')
     assert config is None or isinstance(config, list), \
index ef5b06bfa9df9ca74d1b1837b72c5092b54df1fc..819de3441104a7a651ccb1e3b6b530545fba5ff9 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Most ceph console logging
+"""
 import contextlib
 import logging
 
index ce73f4d54a1a2996fce793456a05c69d0e8de51f..9d318055bde7ea9ee30925fed36546de6611f13a 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Kernel installation task
+"""
 from cStringIO import StringIO
 
 import logging
@@ -45,6 +48,9 @@ def normalize_config(ctx, config):
 
     If config is None or just specifies a version to use,
     it is applied to all nodes.
+
+    :param ctx: Context
+    :param config: Configuration
     """
     if config is None or \
             len(filter(lambda x: x in ['tag', 'branch', 'sha1', 'kdb',
@@ -74,6 +80,12 @@ def normalize_config(ctx, config):
 def _find_arch_and_dist(ctx):
     """
     Return the arch and distro value as a tuple.
+
+    Currently this only returns armv7l on the quantal distro or x86_64
+    on the precise distro
+  
+    :param ctx: Context
+    :returns: arch,distro
     """
     info = ctx.config.get('machine_type', 'plana')
     if teuthology.is_arm(info):
@@ -81,6 +93,13 @@ def _find_arch_and_dist(ctx):
     return ('x86_64', 'precise')
 
 def validate_config(ctx, config):
+    """
+    Make sure that all kernels in the list of remove kernels
+    refer to the same kernel.
+
+    :param ctx: Context
+    :param config: Configuration
+    """
     for _, roles_for_host in ctx.cluster.remotes.iteritems():
         kernel = None
         for role in roles_for_host:
@@ -94,17 +113,27 @@ def validate_config(ctx, config):
                     del config[role]
 
 def _vsplitter(version):
-    """kernels from Calxeda are named ...ceph-<sha1>...highbank
-    kernels that we generate named ...-g<sha1>
+    """Kernels from Calxeda are named ...ceph-<sha1>...highbank.
+    Kernels that we generate are named ...-g<sha1>.
     This routine finds the text in front of the sha1 that is used by
     need_to_install() to extract information from the kernel name.
-    """
 
+    :param version: Name of the kernel
+    """
     if version.endswith('highbank'):
         return 'ceph-'
     return '-g'
 
 def need_to_install(ctx, role, sha1):
+    """
+    Check to see if we need to install a kernel.  Get the version
+    of the currently running kernel, extract the sha1 value from 
+    its name, and compare it against the value passed in.
+
+    :param ctx: Context
+    :param role: machine associated with each role
+    :param sha1: sha1 to compare against (used in checking)
+    """
     ret = True
     log.info('Checking kernel version of {role}, want {sha1}...'.format(
             role=role,
@@ -137,6 +166,12 @@ def need_to_install(ctx, role, sha1):
     return ret
 
 def install_firmware(ctx, config):
+    """
+    Go to the github to get the latest firmware.
+
+    :param ctx: Context
+    :param config: Configuration
+    """
     linux_firmware_git_upstream = 'git://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git'
     uri = teuth_config.linux_firmware_git_url or linux_firmware_git_upstream
     fw_dir = '/lib/firmware/updates'
@@ -183,6 +218,12 @@ def install_firmware(ctx, config):
             )
 
 def download_deb(ctx, config):
+    """
+    Download a Debian kernel and copy the assocated linux image.
+
+    :param ctx: Context
+    :param config: Configuration
+    """
     procs = {}
     for role, src in config.iteritems():
         (role_remote,) = ctx.cluster.only(role).remotes.keys()
@@ -239,6 +280,14 @@ def download_deb(ctx, config):
 
 
 def _no_grub_link(in_file, remote, kernel_ver):
+    """
+    Copy and link kernel related files if grub cannot be used
+    (as is the case in Arm kernels)
+
+    :param infile: kernel file or image file to be copied.
+    :param remote: remote machine 
+    :param kernel_ver: kernel version
+    """
     boot1 = '/boot/%s' % in_file
     boot2 = '%s.old' % boot1
     remote.run(
@@ -251,6 +300,17 @@ def _no_grub_link(in_file, remote, kernel_ver):
     )
 
 def install_and_reboot(ctx, config):
+    """
+    Install and reboot the kernel.  This mostly performs remote
+    installation operations.   The code does check for Arm images
+    and skips grub operations if the kernel is Arm.  Otherwise, it
+    extracts kernel titles from submenu entries and makes the appropriate
+    grub calls.   The assumptions here are somewhat simplified in that
+    it expects kernel entries to be present under submenu entries.
+
+    :param ctx: Context
+    :param config: Configuration
+    """
     procs = {}
     kernel_title = ''
     for role, src in config.iteritems():
@@ -390,6 +450,13 @@ def install_and_reboot(ctx, config):
         proc.exitstatus.get()
 
 def enable_disable_kdb(ctx, config):
+    """
+    Enable kdb on remote machines in use.  Disable on those that are
+    not in use.
+
+    :param ctx: Context
+    :param config: Configuration
+    """
     for role, enable in config.iteritems():
         (role_remote,) = ctx.cluster.only(role).remotes.keys()
         if "mira" in role_remote.name:
@@ -417,6 +484,10 @@ def wait_for_reboot(ctx, need_install, timeout):
     """
     Loop reconnecting and checking kernel versions until
     they're all correct or the timeout is exceeded.
+
+    :param ctx: Context
+    :param need_install: list of packages that we need to reinstall.
+    :param timeout: number of second before we timeout.
     """
     import time
     starttime = time.time()
@@ -484,6 +555,8 @@ def task(ctx, config):
         kernel:
           kdb: true
 
+    :param ctx: Context
+    :param config: Configuration
     """
     assert config is None or isinstance(config, dict), \
         "task kernel only supports a dictionary for configuration"
index dc46dac1c08acdb035a99a5fd9af8ec3ae87fbd9..55bb937f6c5cf1d8638a06684ab90a2633593072 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Export/Unexport a ``nfs server`` client.
+"""
 import contextlib
 import logging
 import os
@@ -51,6 +54,8 @@ def task(ctx, config):
         ro,sync,wdelay,hide,nocrossmnt,secure,root_squash,no_all_squash,
         no_subtree_check,secure_locks,acl,anonuid=65534,anongid=65534
 
+    :param ctx: Context
+    :param config: Configuration
     """
     log.info('Exporting nfs server...')
 
@@ -114,7 +119,7 @@ def task(ctx, config):
             Prevent bogus clients from old runs from access our 
             export.  Specify all specify node addresses for this run.
             """
-            ips = [host for (host, port) in (remote.ssh.get_transport().getpeername() for (remote, roles) in ctx.cluster.remotes.items())]
+            ips = [host for (host, _) in (remote.ssh.get_transport().getpeername() for (remote, roles) in ctx.cluster.remotes.items())]
             for ip in ips:
                 args += [ '{ip}:{MNT}'.format(ip=ip, MNT=mnt) ]
 
index 753362554cf48a87fe8be6ee77e1b5811601bded..8a84514651ce0c96d077f12346db526ae746182d 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Localdir
+"""
 import contextlib
 import logging
 import os
@@ -24,6 +27,8 @@ def task(ctx, config):
         - localdir: [client.2]
         - interactive:
 
+    :param ctx: Context
+    :param config: Configuration
     """
     log.info('Creating local mnt dirs...')
 
index cf76950eb5f33e4cf34cd1dadce9f24544d45b84..10ac1e8e91b29921ebbe37934b7ad0d124036b27 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Locking tests
+"""
 import logging
 import os
 
@@ -37,6 +40,9 @@ def task(ctx, config):
       
     In the past this test would have failed; there was a bug where waitlocks weren't
     cleaned up if the process failed. More involved scenarios are also possible.
+
+    :param ctx: Context
+    :param config: Configuration
     """
     log.info('Starting lockfile')
     try:
@@ -177,6 +183,9 @@ def task(ctx, config):
 # task
 
 def lock_one(op, ctx):
+    """
+    Perform the individual lock
+    """
     log.debug('spinning up locker with op={op_}'.format(op_=op))
     timeout = None
     proc = None
index 06c84512580424fb2db47659ae4cf50e8a9afc13..929ad45043dca28523a32e53b2965c52b896e66a 100755 (executable)
@@ -1,3 +1,6 @@
+"""
+loctests
+"""
 import logging
 
 from ..orchestra import run
@@ -22,6 +25,9 @@ def task(ctx, config):
            [client.0, client.1]
 
     This task does not yield; there would be little point.
+
+    :param ctx: Context
+    :param config: Configuration
     """
 
     assert isinstance(config, list)
index d7c0fc3c118c372598d8e5fed93db3af29a03d91..700a300bf033e1d2eea488b511470cd40ad9b1e2 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Lost_unfound
+"""
 import logging
 import ceph_manager
 from teuthology import misc as teuthology
@@ -8,6 +11,8 @@ log = logging.getLogger(__name__)
 def task(ctx, config):
     """
     Test handling of lost objects.
+
+    A pretty rigid cluseter is brought up andtested by this task
     """
     if config is None:
         config = {}
index cf9d5b54da56c24a39aad9b1aac030f361227b77..32b9d562bf46aff261877eb35cd031b0088b42c0 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Force pg creation on all osds
+"""
 from teuthology import misc as teuthology
 from ..orchestra import run
 import logging
index 71b2207abba555412a1594def36549ca466919f8..c878648c4113789e233b40e0f115cddf26efb35f 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Thrash mds by simulating failures
+"""
 import logging
 import contextlib
 import ceph_manager
@@ -100,13 +103,18 @@ class MDSThrasher:
     self.weight = weight
 
   def log(self, x):
+    """Write data to logger assigned to this MDThrasher""" 
     self.logger.info(x)
 
   def do_join(self):
+    """Thread finished"""
     self.stopping = True
     self.thread.get()
 
   def do_thrash(self):
+    """
+    Perform the random thrashing action
+    """
     self.log('starting mds_do_thrash for failure group: ' + ', '.join(['mds.{_id}'.format(_id=_f) for _f in self.failure_group]))
     while not self.stopping:
       delay = self.max_thrash_delay
index 514ea47e53dcda628dcbe20d3fb14db840db8283..bfa2cdf78f15dfe348dc7d4f2aaf3d345847d050 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Monitor recovery
+"""
 import logging
 import ceph_manager
 from teuthology import misc as teuthology
index 773ab7645ad206ca9242ac1c941384c7adc84a87..6d2381ee58e09a28b5425dd061db36314403f07a 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Start mpi processes (and allow commands to be run inside process)
+"""
 import logging
 
 from teuthology import misc as teuthology
@@ -52,6 +55,8 @@ def task(ctx, config):
             clients:
               - rm -f {testdir}/gmnt
 
+    :param ctx: Context
+    :param config: Configuration
     """
     assert isinstance(config, dict), 'task mpi got invalid config'
     assert 'exec' in config, 'task mpi got invalid config, missing exec'
index 7d0199a44ece04cb1ece18e278c9c9a51e95dd51..bc22b470593d4d8dc4beaf16ca7bf814ff1124d2 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Multibench testing
+"""
 import contextlib
 import logging
 import radosbench
@@ -33,6 +36,7 @@ def task(ctx, config):
         "please list clients to run on"
 
     def run_one(num):
+    """Run test spawn from gevent"""
         start = time.time()
         benchcontext = copy.copy(config.get('radosbench'))
         iterations = 0
index 52123f577a7d4b71405df9eb83161411b40a82ce..72a2981097349214a7e894904f4c4553478afdb0 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Nfs client tester
+"""
 import contextlib
 import logging
 import os
index caa9deec2ff1410b1847a1d1232502b9dfd26ca7..c7b181403f406250469c1b189ef5cca8144816c1 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Null task
+"""
 def task(ctx, config):
     """
     This task does nothing.
index 544b88640281a44694fd2b8b7b1556718121422c..1696c55214aacb54472a646f1cbc07676eed5845 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Test Object locations going down
+"""
 import logging
 import ceph_manager
 from teuthology import misc as teuthology
index 0e8ca6a4bb00ad1e0c4e86809b58ad6517dadffb..7d2535453231aee9093820093fc79c97296fd23a 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Run omapbench executable within teuthology
+"""
 import contextlib
 import logging
 
index e69884876cb97ed510361615dd767b459b04dca5..d80ea22ef22484c95c754d5b28d87c5a586534f7 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Osd backfill test
+"""
 import logging
 import ceph_manager
 import time
@@ -8,6 +11,9 @@ log = logging.getLogger(__name__)
 
 
 def rados_start(ctx, remote, cmd):
+    """
+    Run a remote rados command (currently used to only write data)
+    """
     log.info("rados %s" % ' '.join(cmd))
     testdir = teuthology.get_testdir(ctx)
     pre = [
index 15ae7b54252513cf07346dd888204ea10821803f..39b5b5c530096c8a21b2cef75875e67caed1378a 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Handle osdfailsafe configuration settings (nearfull ratio and full ratio)
+"""
 from cStringIO import StringIO
 import logging
 import time
index f6d4225da2fb6fb4d0d48fc42c57e4e963f8f89f..1ff17335b15e79fb3006e55214973f3f20b8afc2 100644 (file)
@@ -1,3 +1,6 @@
+"""
+osd recovery
+"""
 import logging
 import ceph_manager
 import time
@@ -8,6 +11,9 @@ log = logging.getLogger(__name__)
 
 
 def rados_start(testdir, remote, cmd):
+    """
+    Run a remote rados command (currently used to only write data)
+    """
     log.info("rados %s" % ' '.join(cmd))
     pre = [
         'adjust-ulimits',
index e441e9e010da937b48b8057d0df6c8af47de001c..4cfb67879e90fc4942b1010009084159ebe9b813 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Task to group parallel running tasks
+"""
 import sys
 import logging
 
@@ -28,7 +31,7 @@ def task(ctx, config):
     That is, if the entry is not a dict, we will look it up in the top-level
     config.
 
-    Sequential task and Parallel tasks can be nested.
+    Sequential tasks and Parallel tasks can be nested.
     """
 
     log.info('starting parallel...')
@@ -40,6 +43,7 @@ def task(ctx, config):
             p.spawn(_run_spawned, ctx, confg, taskname)
 
 def _run_spawned(ctx,config,taskname):
+    """Run one of the tasks (this runs in parallel with others)"""
     mgr = {}
     try:
         log.info('In parallel, running task %s...' % taskname)
index 43fb187cb4257bb8939c921495c47bc6e16a39c7..04babfca9b24e6ebe01bcb56454d1cf33ad7abdd 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Parallel contextmanager test
+"""
 import contextlib
 import logging
 
index 3fb8b4b6f077d233d00cf5e929230a0ab5f2e33f..8006c3812ad7a777e27f433d0c56e7a8d393be3e 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Peer test (Single test, not much configurable here)
+"""
 import logging
 import json
 
index 9069ef74fa2d9e37a04f7a84590b27e0bbe983e7..742ac0010bc2228728775374f6f2925bc059e53f 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Handle parallel execution on remote hosts
+"""
 import logging
 
 from teuthology import misc as teuthology
@@ -10,10 +13,11 @@ from gevent import queue as queue
 from gevent import event as event
 
 def _init_barrier(barrier_queue, remote):
+    """current just queues a remote host""" 
     barrier_queue.put(remote)
 
 def _do_barrier(barrier, barrier_queue, remote):
-    # special case for barrier
+    """special case for barrier"""
     barrier_queue.get()
     if barrier_queue.empty():
         barrier.set()
@@ -29,6 +33,7 @@ def _do_barrier(barrier, barrier_queue, remote):
         barrier.wait()
 
 def _exec_host(barrier, barrier_queue, remote, sudo, testdir, ls):
+    """Execute command remotely"""
     log.info('Running commands on host %s', remote.name)
     args = [
         'TESTDIR={tdir}'.format(tdir=testdir),
@@ -55,6 +60,7 @@ def _exec_host(barrier, barrier_queue, remote, sudo, testdir, ls):
     tor.wait([r])
 
 def _generate_remotes(ctx, config):
+    """Return remote roles and the type of role specified in config"""
     if 'all' in config and len(config) == 1:
         ls = config['all']
         for remote in ctx.cluster.remotes.iterkeys():
index 45685015288d49ce41b01945e1d3fe35280bd6cf..db93107a9871aa276279a9875ab50b622fb1c847 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Qemu task
+"""
 from cStringIO import StringIO
 
 import contextlib
@@ -17,6 +20,9 @@ DEFAULT_MEM = 4096 # in megabytes
 
 @contextlib.contextmanager
 def create_dirs(ctx, config):
+    """
+    Handle directory creation and cleanup
+    """
     testdir = teuthology.get_testdir(ctx)
     for client, client_config in config.iteritems():
         assert 'test' in client_config, 'You must specify a test to run'
@@ -42,6 +48,7 @@ def create_dirs(ctx, config):
 
 @contextlib.contextmanager
 def generate_iso(ctx, config):
+    """Execute system commands to generate iso"""
     log.info('generating iso...')
     testdir = teuthology.get_testdir(ctx)
     for client, client_config in config.iteritems():
@@ -120,6 +127,7 @@ def generate_iso(ctx, config):
 
 @contextlib.contextmanager
 def download_image(ctx, config):
+    """Downland base image, remove image file when done"""
     log.info('downloading base image')
     testdir = teuthology.get_testdir(ctx)
     for client, client_config in config.iteritems():
@@ -148,6 +156,7 @@ def download_image(ctx, config):
 
 @contextlib.contextmanager
 def run_qemu(ctx, config):
+    """Setup kvm environment and start qemu"""
     procs = []
     testdir = teuthology.get_testdir(ctx)
     for client, client_config in config.iteritems():
index 2082e1771778c28f6913fa02b924a75eddaa84c7..8e4f019a52e830365718ddafb06a6f4e8a6d9da0 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Rados modle-based integration tests
+"""
 import contextlib
 import logging
 import gevent
@@ -84,6 +87,7 @@ def task(ctx, config):
                 ])
 
     def thread():
+        """Thread spawned by gevent"""
         if not hasattr(ctx, 'manager'):
             first_mon = teuthology.get_first_mon(ctx, config)
             (mon,) = ctx.cluster.only(first_mon).remotes.iterkeys()
index ca5ace2c7b97d7dfe29134512005640a9bad61ba..85e85aaafe8a8bd9901f4a21a476dfba0348487d 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Rados benchmarking
+"""
 import contextlib
 import logging
 
index f91747305a6e69306267206c3c8b016a42db9582..e5945bf422e5d0032fc92582dc3add8c7077870e 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Rgw admin testing against a running instance
+"""
 # The test cases in this file have been annotated for inventory.
 # To extract the inventory (in csv format) use the command:
 #
@@ -24,6 +27,7 @@ log = logging.getLogger(__name__)
 
 
 def successful_ops(out):
+    """Extract total from the first summary entry (presumed to be only one)"""
     summary = out['summary']
     if len(summary) == 0:
         return 0
index 014a1b1441349077b6ca60f452839a9dd14eb33f..5b7dcdca1a75b0f5057c6c51551847c9a70ef12c 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Run rados gateway agent in test mode
+"""
 import contextlib
 import logging
 import argparse
index 6164a229a8f7309a344bd44a56cabad23a9218e8..6e8112732cbb0eea7318185776cecb58877da25c 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Rbd testing task
+"""
 import contextlib
 import logging
 import os
@@ -11,6 +14,9 @@ from teuthology.parallel import parallel
 log = logging.getLogger(__name__)
 
 def default_image_name(role):
+    """
+    Currently just append role to 'testimage.' string
+    """
     return 'testimage.{role}'.format(role=role)
 
 @contextlib.contextmanager
@@ -272,6 +278,7 @@ def mount(ctx, config):
         role_images = [(role, None) for role in config]
 
     def strip_client_prefix(role):
+        """Currently just removes 'client.' from start of role name"""
         PREFIX = 'client.'
         assert role.startswith(PREFIX)
         id_ = role[len(PREFIX):]
@@ -325,10 +332,12 @@ def mount(ctx, config):
                     ]
                 )
 
-# Determine the canonical path for a given path on the host
-# representing the given role.  A canonical path contains no
-# . or .. components, and includes no symbolic links.
 def canonical_path(ctx, role, path):
+    """
+    Determine the canonical path for a given path on the host
+    representing the given role.  A canonical path contains no
+    . or .. components, and includes no symbolic links.
+    """
     version_fp = StringIO()
     ctx.cluster.only(role).run(
         args=[ 'readlink', '-f', path ],
@@ -374,6 +383,9 @@ def run_xfstests(ctx, config):
     yield
 
 def run_xfstests_one_client(ctx, role, properties):
+    """
+    Spawned routine to handle xfs tests for a single client
+    """
     testdir = teuthology.get_testdir(ctx)
     try:
         count = properties.get('count')
index 97d2850877290235cdadb77e1bc6cd6f203e9777..f9e05ca7f6a16cec2e5e23eda5696c58050eecff 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Run fsx on an rbd image
+"""
 import contextlib
 import logging
 
@@ -38,6 +41,7 @@ def task(ctx, config):
     yield
 
 def _run_one_client(ctx, config, role):
+    """Spawned task that runs the client"""
     testdir = teuthology.get_testdir(ctx)
     (remote,) = ctx.cluster.only(role).remotes.iterkeys()
     remote.run(
index c7ba628b52a2bb93e08bcab4e5baf60e9c736e27..d34d31af6b335c68aaae8fa60d3e0443531aeb46 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Rest Api
+"""
 import logging
 import contextlib
 import time
@@ -12,6 +15,9 @@ log = logging.getLogger(__name__)
 
 @contextlib.contextmanager
 def run_rest_api_daemon(ctx, api_clients):
+    """
+    Wrapper starts the rest api daemons
+    """
     if not hasattr(ctx, 'daemons'):
         ctx.daemons = CephState()
     remotes = ctx.cluster.only(teuthology.is_type('client')).remotes
index ee90fb20c16f2c1d1fe72f2695546886119707cf..87ca2b099e32298ede9e6790b76d360566c71371 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Daemon restart
+"""
 import logging
 import pipes
 
@@ -8,6 +11,9 @@ from ..orchestra import run
 log = logging.getLogger(__name__)
 
 def restart_daemon(ctx, config, role, id_, *args):
+    """
+    Handle restart (including the execution of the command parameters passed)
+    """
     log.info('Restarting {r}.{i} daemon...'.format(r=role, i=id_))
     daemon = ctx.daemons.get_daemon(role, id_)
     log.debug('Waiting for exit of {r}.{i} daemon...'.format(r=role, i=id_))
@@ -24,6 +30,7 @@ def restart_daemon(ctx, config, role, id_, *args):
         daemon.restart()
 
 def get_tests(ctx, config, role, remote, testdir):
+    """Download restart tests"""
     srcdir = '{tdir}/restart.{role}'.format(tdir=testdir, role=role)
 
     refspec = config.get('branch')
index b6281b9617c118ce2d611e5c3929e01eb0b9dc99..c2e6e6a21747b62de4bfa936b399b27f1dae9955 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Samba
+"""
 import contextlib
 import logging
 import sys
@@ -8,6 +11,13 @@ from ..orchestra import run
 log = logging.getLogger(__name__)
 
 def get_sambas(ctx, roles):
+    """
+    Scan for roles that are samba.  Yield the id of the the samba role
+    (samba.0, samba.1...)  and the associated remote site 
+    
+    :param ctx: Context
+    :param roles: roles for this test (extracted from yaml files)
+    """
     for role in roles:
         assert isinstance(role, basestring)
         PREFIX = 'samba.'
@@ -65,6 +75,8 @@ def task(ctx, config):
     role, the default behavior is to enable the ceph UNC //localhost/ceph
     and use the ceph vfs module as the smbd backend.
 
+    :param ctx: Context
+    :param config: Configuration
     """
     log.info("Setting up smbd with ceph vfs...")
     assert config is None or isinstance(config, list) or isinstance(config, dict), \
index c1401de6ed06365779c1c97e57010562c8ce098f..7a25300a677dc8e38f53e7d577a26a2aacb4e80b 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Scrub osds
+"""
 import contextlib
 import gevent
 import logging
@@ -59,7 +62,13 @@ def task(ctx, config):
         scrub_proc.do_join()
 
 class Scrubber:
+    """
+    Scrubbing is actually performed during initialzation
+    """
     def __init__(self, manager, config):
+        """
+        Spawn scrubbing thread upon completion.
+        """
         self.ceph_manager = manager
         self.ceph_manager.wait_for_clean()
 
@@ -72,6 +81,7 @@ class Scrubber:
 
         else:
             def tmp(x):
+                """Local display"""
                 print x
             self.log = tmp
 
@@ -82,10 +92,12 @@ class Scrubber:
         self.thread = gevent.spawn(self.do_scrub)
 
     def do_join(self):
+        """Scrubbing thread finished"""
         self.stopping = True
         self.thread.get()
 
     def do_scrub(self):
+        """Perform the scrub operation"""
         frequency = self.config.get("frequency", 30)
         deep = self.config.get("deep", 0)
 
index 36967a86e939dedaf795f2ef2fd6238f0b3d4ca2..3443ae9f45e92500c9d789bd4fa32e243aa69919 100644 (file)
@@ -1,3 +1,4 @@
+"""Scrub testing"""
 from cStringIO import StringIO
 
 import logging
index 505bb65d3e7e9133909439dbbe6a1faaf17ebd10..690d60f11851448162de5830ad317c81c15c4ffe 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Task sequencer
+"""
 import sys
 import logging
 
@@ -28,7 +31,10 @@ def task(ctx, config):
     That is, if the entry is not a dict, we will look it up in the top-level
     config.
 
-    Sequential task and Parallel tasks can be nested.
+    Sequential tasks and Parallel tasks can be nested.
+
+    :param ctx: Context
+    :param config: Configuration
     """
     stack = []
     try:
index cb07a3f35d9075b71c0b9be1025b6d3bd76a972a..4e36d599b6df57f3c88ecdb44d07a675f6f2ada2 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Sleep task
+"""
 import logging
 import time
 
@@ -18,6 +21,8 @@ def task(ctx, config):
            duration: 10
        - interactive:
 
+    :param ctx: Context
+    :param config: Configuration
     """
     if not config:
         config = {}
index 4b4155832bcd453de9c0f32c53299fe4b3506591..74a12c2f8f7ebd9eb0a1ffe438f55c8e2a9fd8d3 100644 (file)
@@ -1,3 +1,7 @@
+"""
+Parallel and sequential task tester.  Not used by any ceph tests, but used to
+unit test the parallel and sequential tasks
+"""
 import logging
 import contextlib
 import time
index 1702dbdfd5321a850de558710abf2ed8e60f9ce9..075e1f83c75cb1d26ee30771995ca3c08a6d0af4 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Thrash -- Simulate random osd failures.
+"""
 import contextlib
 import logging
 import ceph_manager
index 2a78bba0c0822da7518de93750215f4e06a1ac47..d47830f44e53106ff45d63463590754e93259eec 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Timer task
+"""
 import logging
 import contextlib
 import datetime
index da52ba010fd870a510a8dfc40daacf5071186811..ab611c3dd4a70ae8d8bd4d17703a395e3ebf6b02 100644 (file)
@@ -1,3 +1,6 @@
+"""
+test_stress_watch task
+"""
 import contextlib
 import logging
 import proc_thrasher
index e84efb22215d3704a3c208a8904b7f83ddd6a5a9..3749d4716504e523ede3a58062b4e3c32fe9785d 100644 (file)
@@ -1,3 +1,6 @@
+"""
+Workunit task -- Run ceph on sets of specific clients
+"""
 import logging
 import pipes
 import os
@@ -10,7 +13,7 @@ log = logging.getLogger(__name__)
 
 def task(ctx, config):
     """
-    Run ceph all workunits found under the specified path.
+    Run ceph on all workunits found under the specified path.
 
     For example::
 
@@ -48,6 +51,9 @@ def task(ctx, config):
             env:
               FOO: bar
               BAZ: quux
+
+    :param ctx: Context
+    :param config: Configuration
     """
     assert isinstance(config, dict)
     assert isinstance(config.get('clients'), dict), \
@@ -100,14 +106,22 @@ def task(ctx, config):
         PREFIX = 'client.'
         assert role.startswith(PREFIX)
         if created_dir_dict[role]:
-            _delete_dir(ctx, role, config.get('subdir'))
+            _delete_dir(ctx, role)
+
+def _delete_dir(ctx, role):
+    """
+    Delete file used by this role, and delete the directory that this
+    role appeared in.
 
-def _delete_dir(ctx, role, subdir):
+    :param ctx: Context
+    :param role: "role.#" where # is used for the role id.
+    """
     PREFIX = 'client.'
     testdir = teuthology.get_testdir(ctx)
     id_ = role[len(PREFIX):]
     (remote,) = ctx.cluster.only(role).remotes.iterkeys()
     mnt = os.path.join(testdir, 'mnt.{id}'.format(id=id_))
+    # Is there any reason why this is not: join(mnt, role) ?
     client = os.path.join(mnt, 'client.{id}'.format(id=id_))
     try:
         remote.run(
@@ -135,6 +149,14 @@ def _delete_dir(ctx, role, subdir):
         log.exception("Caught an execption deleting dir {dir}".format(dir=mnt))
 
 def _make_scratch_dir(ctx, role, subdir):
+    """
+    Make scratch directories for this role.  This also makes the mount
+    point if that directory does not exist.
+
+    :param ctx: Context
+    :param role: "role.#" where # is used for the role id.
+    :param subdir: use this subdir (False if not used)
+    """
     retVal = False
     PREFIX = 'client.'
     id_ = role[len(PREFIX):]
@@ -200,6 +222,17 @@ def _make_scratch_dir(ctx, role, subdir):
     return retVal
 
 def _spawn_on_all_clients(ctx, refspec, tests, env, subdir):
+    """
+    Make a scratch directory for each client in the cluster, and then for each
+    test spawn _run_tests for each role.    
+
+    :param ctx: Context
+    :param refspec: branch, sha1, or version tag used to identify this
+                    build 
+    :param tests: specific tests specified.
+    :param env: evnironment set in yaml file.  Could be None.
+    :param subdir: subdirectory set in yaml file.  Could be None
+    """
     client_generator = teuthology.all_roles_of_type(ctx.cluster, 'client')
     client_remotes = list()
     for client in client_generator:
@@ -215,9 +248,21 @@ def _spawn_on_all_clients(ctx, refspec, tests, env, subdir):
     # cleanup the generated client directories
     client_generator = teuthology.all_roles_of_type(ctx.cluster, 'client')
     for client in client_generator:
-        _delete_dir(ctx, 'client.{id}'.format(id=client), subdir)
+        _delete_dir(ctx, 'client.{id}'.format(id=client))
 
 def _run_tests(ctx, refspec, role, tests, env, subdir=None):
+    """
+    Run the individual test.  Create a scratch directory and then extract the workunits
+    from the git-hub.  Make the executables, and then run the tests.
+    Clean up (remove files created) after the tests are finished.
+
+    :param ctx: Context
+    :param refspec: branch, sha1, or version tag used to identify this
+                    build 
+    :param tests: specific tests specified.
+    :param env: evnironment set in yaml file.  Could be None.
+    :param subdir: subdirectory set in yaml file.  Could be None
+    """
     testdir = teuthology.get_testdir(ctx)
     assert isinstance(role, basestring)
     PREFIX = 'client.'