New get_child_pids function

Change-Id: I3d5a19b27aa9a75265ad40fb3ca8f2e6ee7bd81c
Signed-off-by: Michael Walsh <micwalsh@us.ibm.com>
diff --git a/lib/gen_misc.py b/lib/gen_misc.py
index 75487c1..84eb894 100755
--- a/lib/gen_misc.py
+++ b/lib/gen_misc.py
@@ -12,6 +12,12 @@
 import StringIO
 import re
 import socket
+import tempfile
+try:
+    import psutil
+    psutil_imported = True
+except ImportError:
+    psutil_imported = False
 
 import gen_print as gp
 import gen_cmd as gc
@@ -401,3 +407,57 @@
         return ((2**bit_width) - number) * -1
     else:
         return number
+
+
+def get_child_pids(quiet=1):
+
+    r"""
+    Get and return a list of pids representing all first-generation processes
+    that are the children of the current process.
+
+    Example:
+
+    children = get_child_pids()
+    print_var(children)
+
+    Output:
+    children:
+      children[0]:           9123
+
+    Description of argument(s):
+    quiet                           Display output to stdout detailing how
+                                    this child pids are obtained.
+    """
+
+    if psutil_imported:
+        # If "import psutil" worked, find child pids using psutil.
+        current_process = psutil.Process()
+        return [x.pid for x in current_process.children(recursive=False)]
+    else:
+        # Otherwise, find child pids using shell commands.
+        print_output = not quiet
+
+        ps_cmd_buf = "ps --no-headers --ppid " + str(os.getpid()) +\
+            " -o pid,args"
+        # Route the output of ps to a temporary file for later grepping.
+        # Avoid using " | grep" in the ps command string because it creates
+        # yet another process which is of no interest to the caller.
+        temp = tempfile.NamedTemporaryFile()
+        temp_file_path = temp.name
+        gc.shell_cmd(ps_cmd_buf + " > " + temp_file_path,
+                     print_output=print_output)
+        # Sample contents of the temporary file:
+        # 30703 sleep 2
+        # 30795 /bin/bash -c ps --no-headers --ppid 30672 -o pid,args >
+        # /tmp/tmpqqorWY
+        # Use egrep to exclude the "ps" process itself from the results
+        # collected with the prior shell_cmd invocation.  Only the other
+        # children are of interest to the caller.  Use cut on the grep results
+        # to obtain only the pid column.
+        rc, output = \
+            gc.shell_cmd("egrep -v '" + re.escape(ps_cmd_buf) + "' "
+                         + temp_file_path + " | cut -c1-5",
+                         print_output=print_output)
+        # Split the output buffer by line into a list.  Strip each element of
+        # extra spaces and convert each element to an integer.
+        return map(int, map(str.strip, filter(None, output.split("\n"))))