1e7e9171eSGeorge Keishing#!/usr/bin/env python3
27423c01aSMichael Walsh
37423c01aSMichael Walshr"""
47423c01aSMichael WalshThis module provides functions which are useful for running plug-ins.
57423c01aSMichael Walsh"""
67423c01aSMichael Walsh
7e635ddc0SGeorge Keishingimport glob
8*20f38712SPatrick Williamsimport os
9*20f38712SPatrick Williamsimport sys
107423c01aSMichael Walsh
11e635ddc0SGeorge Keishingimport gen_misc as gm
12*20f38712SPatrick Williamsimport gen_print as gp
137423c01aSMichael Walsh
147423c01aSMichael Walsh# Some help text that is common to more than one program.
15*20f38712SPatrick Williamsplug_in_dir_paths_help_text = (
16*20f38712SPatrick Williams    "This is a colon-separated list of plug-in directory paths.  If one"
17*20f38712SPatrick Williams    + " of the entries in the list is a plain directory name (i.e. no"
18*20f38712SPatrick Williams    + " path info), it will be taken to be a native plug-in.  In that case,"
19*20f38712SPatrick Williams    + ' %(prog)s will search for the native plug-in in the "plug-ins"'
20*20f38712SPatrick Williams    + " subdirectory of each path in the PATH environment variable until it"
21*20f38712SPatrick Williams    + " is found.  Also, integrated plug-ins will automatically be appended"
22*20f38712SPatrick Williams    + " to your plug_in_dir_paths list.  An integrated plug-in is any plug-in"
23*20f38712SPatrick Williams    + ' found using the PATH variable that contains a file named "integrated".'
24*20f38712SPatrick Williams)
257423c01aSMichael Walsh
26*20f38712SPatrick Williamsmch_class_help_text = (
27*20f38712SPatrick Williams    'The class of machine that we are testing (e.g. "op" = "open power",'
28*20f38712SPatrick Williams    + ' "obmc" = "open bmc", etc).'
29*20f38712SPatrick Williams)
307423c01aSMichael Walsh
317423c01aSMichael WalshPATH_LIST = gm.return_path_list()
327423c01aSMichael Walsh
337423c01aSMichael Walsh
347423c01aSMichael Walshdef get_plug_in_base_paths():
357423c01aSMichael Walsh    r"""
367423c01aSMichael Walsh    Get plug-in base paths and return them as a list.
377423c01aSMichael Walsh
38410b1787SMichael Walsh    This function searches the PATH_LIST (created from PATH environment variable) for any paths that have a
39410b1787SMichael Walsh    "plug_ins" subdirectory.  All such paths are considered plug_in_base paths.
407423c01aSMichael Walsh    """
417423c01aSMichael Walsh
427423c01aSMichael Walsh    global PATH_LIST
437423c01aSMichael Walsh
447423c01aSMichael Walsh    plug_in_base_path_list = []
457423c01aSMichael Walsh
467423c01aSMichael Walsh    for path in PATH_LIST:
477423c01aSMichael Walsh        candidate_plug_in_base_path = path + "plug_ins/"
487423c01aSMichael Walsh        if os.path.isdir(candidate_plug_in_base_path):
497423c01aSMichael Walsh            plug_in_base_path_list.append(candidate_plug_in_base_path)
507423c01aSMichael Walsh
517423c01aSMichael Walsh    return plug_in_base_path_list
527423c01aSMichael Walsh
53096cd565SGunnar Mills
54410b1787SMichael Walsh# Define global plug_in_base_path_list and call get_plug_in_base_paths to set its value.
557423c01aSMichael Walshplug_in_base_path_list = get_plug_in_base_paths()
567423c01aSMichael Walsh
577423c01aSMichael Walsh
587423c01aSMichael Walshdef find_plug_in_package(plug_in_name):
597423c01aSMichael Walsh    r"""
60410b1787SMichael Walsh    Find and return the normalized directory path of the specified plug in.  This is done by searching the
61410b1787SMichael Walsh    global plug_in_base_path_list.
627423c01aSMichael Walsh
637423c01aSMichael Walsh    Description of arguments:
64410b1787SMichael Walsh    plug_in_name                    The unqualified name of the plug-in package.
657423c01aSMichael Walsh    """
667423c01aSMichael Walsh
677423c01aSMichael Walsh    global plug_in_base_path_list
687423c01aSMichael Walsh    for plug_in_base_dir_path in plug_in_base_path_list:
69*20f38712SPatrick Williams        candidate_plug_in_dir_path = (
70*20f38712SPatrick Williams            os.path.normpath(plug_in_base_dir_path + plug_in_name) + os.sep
71*20f38712SPatrick Williams        )
727423c01aSMichael Walsh        if os.path.isdir(candidate_plug_in_dir_path):
737423c01aSMichael Walsh            return candidate_plug_in_dir_path
747423c01aSMichael Walsh
757423c01aSMichael Walsh    return ""
767423c01aSMichael Walsh
777423c01aSMichael Walsh
78*20f38712SPatrick Williamsdef validate_plug_in_package(plug_in_dir_path, mch_class="obmc"):
797423c01aSMichael Walsh    r"""
80410b1787SMichael Walsh    Validate the plug in package and return the normalized plug-in directory path.
817423c01aSMichael Walsh
827423c01aSMichael Walsh    Description of arguments:
83410b1787SMichael Walsh    plug_in_dir_path                The "relative" or absolute path to a plug in package directory.
84410b1787SMichael Walsh    mch_class                       The class of machine that we are testing (e.g. "op" = "open power",
85410b1787SMichael Walsh                                    "obmc" = "open bmc", etc).
867423c01aSMichael Walsh    """
877423c01aSMichael Walsh
887423c01aSMichael Walsh    gp.dprint_executing()
897423c01aSMichael Walsh
907423c01aSMichael Walsh    if os.path.isabs(plug_in_dir_path):
917423c01aSMichael Walsh        # plug_in_dir_path begins with a slash so it is an absolute path.
92*20f38712SPatrick Williams        candidate_plug_in_dir_path = (
93*20f38712SPatrick Williams            os.path.normpath(plug_in_dir_path) + os.sep
94*20f38712SPatrick Williams        )
957423c01aSMichael Walsh        if not os.path.isdir(candidate_plug_in_dir_path):
96*20f38712SPatrick Williams            gp.print_error_report(
97*20f38712SPatrick Williams                'Plug-in directory path "'
98*20f38712SPatrick Williams                + plug_in_dir_path
99*20f38712SPatrick Williams                + '" does not exist.\n'
100*20f38712SPatrick Williams            )
1017423c01aSMichael Walsh            exit(1)
1027423c01aSMichael Walsh    else:
103410b1787SMichael Walsh        # The plug_in_dir_path is actually a simple name (e.g. "OBMC_Sample")...
1047423c01aSMichael Walsh        candidate_plug_in_dir_path = find_plug_in_package(plug_in_dir_path)
1057423c01aSMichael Walsh        if candidate_plug_in_dir_path == "":
1067423c01aSMichael Walsh            global PATH_LIST
107*20f38712SPatrick Williams            gp.print_error_report(
108*20f38712SPatrick Williams                'Plug-in directory path "'
109*20f38712SPatrick Williams                + plug_in_dir_path
110*20f38712SPatrick Williams                + '" could not be found'
111004ad3c9SJoy Onyerikwu                + " in any of the following directories:\n"
112*20f38712SPatrick Williams                + gp.sprint_var(PATH_LIST)
113*20f38712SPatrick Williams            )
1147423c01aSMichael Walsh            exit(1)
1157423c01aSMichael Walsh    # Make sure that this plug-in supports us...
1167423c01aSMichael Walsh    supports_file_path = candidate_plug_in_dir_path + "supports_" + mch_class
1177423c01aSMichael Walsh    if not os.path.exists(supports_file_path):
118*20f38712SPatrick Williams        gp.print_error_report(
119*20f38712SPatrick Williams            "The following file path could not be"
120004ad3c9SJoy Onyerikwu            + " found:\n"
121*20f38712SPatrick Williams            + gp.sprint_varx("supports_file_path", supports_file_path)
122004ad3c9SJoy Onyerikwu            + "\nThis file is necessary to indicate that"
123004ad3c9SJoy Onyerikwu            + " the given plug-in supports the class of"
124*20f38712SPatrick Williams            + ' machine we are testing, namely "'
125*20f38712SPatrick Williams            + mch_class
126*20f38712SPatrick Williams            + '".\n'
127*20f38712SPatrick Williams        )
1287423c01aSMichael Walsh        exit(1)
1297423c01aSMichael Walsh
1307423c01aSMichael Walsh    return candidate_plug_in_dir_path
1317423c01aSMichael Walsh
1327423c01aSMichael Walsh
1337423c01aSMichael Walshdef return_integrated_plug_ins(mch_class="obmc"):
1347423c01aSMichael Walsh    r"""
135410b1787SMichael Walsh    Return a list of integrated plug-ins.  Integrated plug-ins are plug-ins which are selected without regard
136410b1787SMichael Walsh    for whether the user has specified them.  In other words, they are "integrated" into the program suite.
137410b1787SMichael Walsh    The programmer designates a plug-in as integrated by putting a file named "integrated" into the plug-in
138410b1787SMichael Walsh    package directory.
1397423c01aSMichael Walsh
1407423c01aSMichael Walsh    Description of arguments:
141410b1787SMichael Walsh    mch_class                       The class of machine that we are testing (e.g. "op" = "open power",
142410b1787SMichael Walsh                                    "obmc" = "open bmc", etc).
1437423c01aSMichael Walsh    """
1447423c01aSMichael Walsh
1457423c01aSMichael Walsh    global plug_in_base_path_list
1467423c01aSMichael Walsh
1477423c01aSMichael Walsh    integrated_plug_ins_list = []
1487423c01aSMichael Walsh
149*20f38712SPatrick Williams    DEBUG_SKIP_INTEGRATED = int(os.getenv("DEBUG_SKIP_INTEGRATED", "0"))
1506cd9cbe5SMichael Walsh
1516cd9cbe5SMichael Walsh    if DEBUG_SKIP_INTEGRATED:
1526cd9cbe5SMichael Walsh        return integrated_plug_ins_list
1536cd9cbe5SMichael Walsh
1547423c01aSMichael Walsh    for plug_in_base_path in plug_in_base_path_list:
1557423c01aSMichael Walsh        # Get a list of all plug-in paths that support our mch_class.
156*20f38712SPatrick Williams        mch_class_candidate_list = glob.glob(
157*20f38712SPatrick Williams            plug_in_base_path + "*/supports_" + mch_class
158*20f38712SPatrick Williams        )
1597423c01aSMichael Walsh        for candidate_path in mch_class_candidate_list:
160*20f38712SPatrick Williams            integrated_plug_in_dir_path = (
161*20f38712SPatrick Williams                os.path.dirname(candidate_path) + os.sep
162*20f38712SPatrick Williams            )
1637423c01aSMichael Walsh            integrated_file_path = integrated_plug_in_dir_path + "integrated"
1647423c01aSMichael Walsh            if os.path.exists(integrated_file_path):
165*20f38712SPatrick Williams                plug_in_name = os.path.basename(
166*20f38712SPatrick Williams                    os.path.dirname(candidate_path)
167*20f38712SPatrick Williams                )
1687423c01aSMichael Walsh                if plug_in_name not in integrated_plug_ins_list:
1697423c01aSMichael Walsh                    # If this plug-in has not already been added to the list...
1707423c01aSMichael Walsh                    integrated_plug_ins_list.append(plug_in_name)
1717423c01aSMichael Walsh
1727423c01aSMichael Walsh    return integrated_plug_ins_list
1737423c01aSMichael Walsh
1747423c01aSMichael Walsh
175*20f38712SPatrick Williamsdef return_plug_in_packages_list(plug_in_dir_paths, mch_class="obmc"):
1767423c01aSMichael Walsh    r"""
177410b1787SMichael Walsh    Return a list of plug-in packages given the plug_in_dir_paths string.  This function calls
178410b1787SMichael Walsh    validate_plug_in_package so it will fail if plug_in_dir_paths contains any invalid plug-ins.
1797423c01aSMichael Walsh
1807423c01aSMichael Walsh    Description of arguments:
181410b1787SMichael Walsh    plug_in_dir_path                The "relative" or absolute path to a plug in package directory.
182410b1787SMichael Walsh    mch_class                       The class of machine that we are testing (e.g. "op" = "open power",
183410b1787SMichael Walsh                                    "obmc" = "open bmc", etc).
1847423c01aSMichael Walsh    """
1857423c01aSMichael Walsh
1867423c01aSMichael Walsh    if plug_in_dir_paths != "":
1877423c01aSMichael Walsh        plug_in_packages_list = plug_in_dir_paths.split(":")
1887423c01aSMichael Walsh    else:
1897423c01aSMichael Walsh        plug_in_packages_list = []
1907423c01aSMichael Walsh
1917423c01aSMichael Walsh    # Get a list of integrated plug-ins (w/o full path names).
1927423c01aSMichael Walsh    integrated_plug_ins_list = return_integrated_plug_ins(mch_class)
193410b1787SMichael Walsh    # Put both lists together in plug_in_packages_list with no duplicates.  NOTE: This won't catch
194410b1787SMichael Walsh    # duplicates if the caller specifies the full path name of a native plug-in but that should be rare
195410b1787SMichael Walsh    # enough.
1967423c01aSMichael Walsh
1977423c01aSMichael Walsh    plug_in_packages_list = plug_in_packages_list + integrated_plug_ins_list
1987423c01aSMichael Walsh
199*20f38712SPatrick Williams    plug_in_packages_list = list(
200*20f38712SPatrick Williams        set(
201*20f38712SPatrick Williams            [
202*20f38712SPatrick Williams                validate_plug_in_package(path, mch_class)
203*20f38712SPatrick Williams                for path in plug_in_packages_list
204*20f38712SPatrick Williams            ]
205*20f38712SPatrick Williams        )
206*20f38712SPatrick Williams    )
2077423c01aSMichael Walsh
2087423c01aSMichael Walsh    return plug_in_packages_list
209