> From: Yunping Zheng <[email protected]>
> 
> This patch adds a systemtap profiler to autotest. Now
> systemtap can run during your test, providing useful
> debug data.
> 
> When you use this profiler on virt tests, you should add
> 
> 'profilers = systemtap'
> 
> and
> 
> 'stap_script_file = file_path_systemtap_script'
> 
> On your test cfg file. If the 'file_path_systemtap_script' you
> assigned is a relative path,the script will try to find
> the file under 'test.virtdir/systemtap'.
> 
> Of course, other tests can use systemtap, just follow the
> example on the control file shipped with the profiler:
> 
> st_script = '/usr/share/systemtap/tapset/timestamp.stp'
> job.profilers.add('systemtap', stap_script_file=st_script)
> job.run_test('sleeptest', seconds=5)
> job.profilers.delete('systemtap')
> 
> Signed-off-by: Lucas Meneghel Rodrigues <[email protected]>
> Signed-off-by: Yunping Zheng <[email protected]>
> ---
>  client/profilers/systemtap/control       |  5 ++
>  client/profilers/systemtap/systemtap.py  | 83
>  ++++++++++++++++++++++++++++++++
>  client/tests/virt/virttest/utils_misc.py |  2 +-
>  3 files changed, 89 insertions(+), 1 deletion(-)
>  create mode 100644 client/profilers/systemtap/__init__.py
>  create mode 100644 client/profilers/systemtap/control
>  create mode 100644 client/profilers/systemtap/systemtap.py
> 
> diff --git a/client/profilers/systemtap/__init__.py
> b/client/profilers/systemtap/__init__.py
> new file mode 100644
> index 0000000..e69de29
> diff --git a/client/profilers/systemtap/control
> b/client/profilers/systemtap/control
> new file mode 100644
> index 0000000..bf600d2
> --- /dev/null
> +++ b/client/profilers/systemtap/control
> @@ -0,0 +1,5 @@
> +# You must provide a path to a systemtap script
> +st_script = '/usr/share/systemtap/tapset/timestamp.stp'
> +job.profilers.add('systemtap', stap_script_file=st_script)
> +job.run_test('sleeptest', seconds=5)
> +job.profilers.delete('systemtap')
> diff --git a/client/profilers/systemtap/systemtap.py
> b/client/profilers/systemtap/systemtap.py
> new file mode 100644
> index 0000000..e050ce2
> --- /dev/null
> +++ b/client/profilers/systemtap/systemtap.py
> @@ -0,0 +1,83 @@
> +"""
> +Autotest systemtap profiler.
> +"""
> +import logging, os, re, subprocess
> +from autotest.client import profiler, os_dep
> +from autotest.client.shared import utils, error
> +
> +
> +class systemtap(profiler.profiler):
> +    """
> +    Tracing test process using systemtap tools.
> +    """
> +    version = 1
> +
> +    def initialize(self, **dargs):
> +        self.is_enabled = False
> +
> +        stap_installed = False
> +        try:
> +            self.stap_path = os_dep.command('stap')
> +            stap_installed = True
> +        except ValueError:
> +            logging.error('Command stap not present')
> +
> +        if stap_installed:
> +            self.is_enabled = True
> +            self.script_name = dargs.get('stap_script_file')
> +            stap_support_cmd = "stap -e 'probe begin {
> log(\"Support\") exit() }'"
> +
> +            if not re.findall("Support",
> utils.system_output(stap_support_cmd)):
> +                logging.warning("Seems your host does not support
> systemtap")
> +                self.is_enabled = False
> +            if not self.script_name:
> +                logging.warning("You should assign a script file")
> +                self.is_enabled = False
> +
> +
> +    def _get_stap_script_name(self, test):
> +        try:
> +            if os.path.isabs(self.script_name):
> +                return self.script_name
> +            else:
> +                return os.path.join(test.virtdir, "systemtap",
> self.script_name)
> +        except AttributeError:
> +            return self.script_name
> +
> +
> +    def start(self, test):
> +        if self.is_enabled:
> +            stap_script = self._get_stap_script_name(test)
> +            if os.path.isfile(stap_script):
> +                cmd = "stap %s"  % (stap_script)

I can't find an easier way to get stap to produce a "started" line, so 
basically I suggest something like:

tmpdir = tempfile.mkdtemp()
tmpfilename = os.path.join(tmpdir, "autotest.stp")
with open(tmpfilename, 'w') as fd:
    fd.write(os.open(stap_script).read() + """

probe begin(99) { printf("profiling started\n"); }
""")

cmd = "stap %s" % (tmpfilename)

And cleanup later of course.

> +                logfile = open(os.path.join(test.profdir,
> "systemtap.log"), 'w')
> +                p = subprocess.Popen(cmd, shell=True,
> stdout=logfile,
> +                                     stderr=subprocess.STDOUT)
> +                self.pid = p.pid
> +            else:
> +                logging.warning("Asked for systemtap profiling, but
> no script "
> +                                "file %s not found", stap_script)
> +                self.is_enabled = False
> +        else:
> +            logging.warning("Asked for systemtap profiling, but it
> couldn't "
> +                            "be initialized")

OK, I don't know the api here, maybe there is a simpler way to do it, but 
basically, read until you see the begin(99) probe output

> +
> +
> +    def stop(self, test):
> +        if self.is_enabled:
> +            try:
> +                term_profiler = "kill -15 %d" % self.pid
> +                # send SIGTERM to iostat and give it a 5-sec timeout
> +                utils.system(term_profiler, timeout=5)
> +            except error.CmdError: # probably times out
> +                pass
> +            # do a ps again to see if iostat is still there
> +            ps_cmd = "ps -p %d | grep stap" % self.pid
> +            out = utils.system_output(ps_cmd, ignore_status=True)
> +            if out != '':
> +                kill_profiler = 'kill -9 %d' % self.pid
> +                utils.system(kill_profiler, ignore_status=True)
> +
> +
> +    def report(self, test):
> +        return None
> diff --git a/client/tests/virt/virttest/utils_misc.py
> b/client/tests/virt/virttest/utils_misc.py
> index 6bd4cd4..18584e8 100644
> --- a/client/tests/virt/virttest/utils_misc.py
> +++ b/client/tests/virt/virttest/utils_misc.py
> @@ -1623,7 +1623,7 @@ def run_tests(parser, job):
>              # Setting up profilers during test execution.
>              profilers = param_dict.get("profilers", "").split()
>              for profiler in profilers:
> -                job.profilers.add(profiler)
> +                job.profilers.add(profiler, **param_dict)
>              # We need only one execution, profiled, hence we're
>              passing
>              # the profile_only parameter to job.run_test().
>              profile_only = bool(profilers) or None
> --
> 1.7.11.4
> 
> 

_______________________________________________
Autotest-kernel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/autotest-kernel

Reply via email to