| George Keishing | e7e9171 | 2021-09-03 11:28:44 -0500 | [diff] [blame] | 1 | #!/usr/bin/env python3 | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 2 |  | 
|  | 3 | r""" | 
|  | 4 | This module provides functions which are useful for running plug-ins. | 
|  | 5 | """ | 
|  | 6 |  | 
| George Keishing | e635ddc | 2022-12-08 07:38:02 -0600 | [diff] [blame] | 7 | import glob | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 8 | import os | 
|  | 9 | import sys | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 10 |  | 
| George Keishing | e635ddc | 2022-12-08 07:38:02 -0600 | [diff] [blame] | 11 | import gen_misc as gm | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 12 | import gen_print as gp | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 13 |  | 
|  | 14 | # Some help text that is common to more than one program. | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 15 | plug_in_dir_paths_help_text = ( | 
|  | 16 | "This is a colon-separated list of plug-in directory paths.  If one" | 
|  | 17 | + " of the entries in the list is a plain directory name (i.e. no" | 
|  | 18 | + " path info), it will be taken to be a native plug-in.  In that case," | 
|  | 19 | + ' %(prog)s will search for the native plug-in in the "plug-ins"' | 
|  | 20 | + " subdirectory of each path in the PATH environment variable until it" | 
|  | 21 | + " is found.  Also, integrated plug-ins will automatically be appended" | 
|  | 22 | + " to your plug_in_dir_paths list.  An integrated plug-in is any plug-in" | 
|  | 23 | + ' found using the PATH variable that contains a file named "integrated".' | 
|  | 24 | ) | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 25 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 26 | mch_class_help_text = ( | 
|  | 27 | 'The class of machine that we are testing (e.g. "op" = "open power",' | 
|  | 28 | + ' "obmc" = "open bmc", etc).' | 
|  | 29 | ) | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 30 |  | 
|  | 31 | PATH_LIST = gm.return_path_list() | 
|  | 32 |  | 
|  | 33 |  | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 34 | def get_plug_in_base_paths(): | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 35 | r""" | 
|  | 36 | Get plug-in base paths and return them as a list. | 
|  | 37 |  | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 38 | This function searches the PATH_LIST (created from PATH environment variable) for any paths that have a | 
|  | 39 | "plug_ins" subdirectory.  All such paths are considered plug_in_base paths. | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 40 | """ | 
|  | 41 |  | 
|  | 42 | global PATH_LIST | 
|  | 43 |  | 
|  | 44 | plug_in_base_path_list = [] | 
|  | 45 |  | 
|  | 46 | for path in PATH_LIST: | 
|  | 47 | candidate_plug_in_base_path = path + "plug_ins/" | 
|  | 48 | if os.path.isdir(candidate_plug_in_base_path): | 
|  | 49 | plug_in_base_path_list.append(candidate_plug_in_base_path) | 
|  | 50 |  | 
|  | 51 | return plug_in_base_path_list | 
|  | 52 |  | 
| Gunnar Mills | 096cd56 | 2018-03-26 10:19:12 -0500 | [diff] [blame] | 53 |  | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 54 | # Define global plug_in_base_path_list and call get_plug_in_base_paths to set its value. | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 55 | plug_in_base_path_list = get_plug_in_base_paths() | 
|  | 56 |  | 
|  | 57 |  | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 58 | def find_plug_in_package(plug_in_name): | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 59 | r""" | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 60 | Find and return the normalized directory path of the specified plug in.  This is done by searching the | 
|  | 61 | global plug_in_base_path_list. | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 62 |  | 
|  | 63 | Description of arguments: | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 64 | plug_in_name                    The unqualified name of the plug-in package. | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 65 | """ | 
|  | 66 |  | 
|  | 67 | global plug_in_base_path_list | 
|  | 68 | for plug_in_base_dir_path in plug_in_base_path_list: | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 69 | candidate_plug_in_dir_path = ( | 
|  | 70 | os.path.normpath(plug_in_base_dir_path + plug_in_name) + os.sep | 
|  | 71 | ) | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 72 | if os.path.isdir(candidate_plug_in_dir_path): | 
|  | 73 | return candidate_plug_in_dir_path | 
|  | 74 |  | 
|  | 75 | return "" | 
|  | 76 |  | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 77 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 78 | def validate_plug_in_package(plug_in_dir_path, mch_class="obmc"): | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 79 | r""" | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 80 | Validate the plug in package and return the normalized plug-in directory path. | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 81 |  | 
|  | 82 | Description of arguments: | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 83 | plug_in_dir_path                The "relative" or absolute path to a plug in package directory. | 
|  | 84 | mch_class                       The class of machine that we are testing (e.g. "op" = "open power", | 
|  | 85 | "obmc" = "open bmc", etc). | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 86 | """ | 
|  | 87 |  | 
|  | 88 | gp.dprint_executing() | 
|  | 89 |  | 
|  | 90 | if os.path.isabs(plug_in_dir_path): | 
|  | 91 | # plug_in_dir_path begins with a slash so it is an absolute path. | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 92 | candidate_plug_in_dir_path = ( | 
|  | 93 | os.path.normpath(plug_in_dir_path) + os.sep | 
|  | 94 | ) | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 95 | if not os.path.isdir(candidate_plug_in_dir_path): | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 96 | gp.print_error_report( | 
|  | 97 | 'Plug-in directory path "' | 
|  | 98 | + plug_in_dir_path | 
|  | 99 | + '" does not exist.\n' | 
|  | 100 | ) | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 101 | exit(1) | 
|  | 102 | else: | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 103 | # The plug_in_dir_path is actually a simple name (e.g. "OBMC_Sample")... | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 104 | candidate_plug_in_dir_path = find_plug_in_package(plug_in_dir_path) | 
|  | 105 | if candidate_plug_in_dir_path == "": | 
|  | 106 | global PATH_LIST | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 107 | gp.print_error_report( | 
|  | 108 | 'Plug-in directory path "' | 
|  | 109 | + plug_in_dir_path | 
|  | 110 | + '" could not be found' | 
|  | 111 | + " in any of the following directories:\n" | 
|  | 112 | + gp.sprint_var(PATH_LIST) | 
|  | 113 | ) | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 114 | exit(1) | 
|  | 115 | # Make sure that this plug-in supports us... | 
|  | 116 | supports_file_path = candidate_plug_in_dir_path + "supports_" + mch_class | 
|  | 117 | if not os.path.exists(supports_file_path): | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 118 | gp.print_error_report( | 
|  | 119 | "The following file path could not be" | 
|  | 120 | + " found:\n" | 
|  | 121 | + gp.sprint_varx("supports_file_path", supports_file_path) | 
|  | 122 | + "\nThis file is necessary to indicate that" | 
|  | 123 | + " the given plug-in supports the class of" | 
|  | 124 | + ' machine we are testing, namely "' | 
|  | 125 | + mch_class | 
|  | 126 | + '".\n' | 
|  | 127 | ) | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 128 | exit(1) | 
|  | 129 |  | 
|  | 130 | return candidate_plug_in_dir_path | 
|  | 131 |  | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 132 |  | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 133 | def return_integrated_plug_ins(mch_class="obmc"): | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 134 | r""" | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 135 | Return a list of integrated plug-ins.  Integrated plug-ins are plug-ins which are selected without regard | 
|  | 136 | for whether the user has specified them.  In other words, they are "integrated" into the program suite. | 
|  | 137 | The programmer designates a plug-in as integrated by putting a file named "integrated" into the plug-in | 
|  | 138 | package directory. | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 139 |  | 
|  | 140 | Description of arguments: | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 141 | mch_class                       The class of machine that we are testing (e.g. "op" = "open power", | 
|  | 142 | "obmc" = "open bmc", etc). | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 143 | """ | 
|  | 144 |  | 
|  | 145 | global plug_in_base_path_list | 
|  | 146 |  | 
|  | 147 | integrated_plug_ins_list = [] | 
|  | 148 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 149 | DEBUG_SKIP_INTEGRATED = int(os.getenv("DEBUG_SKIP_INTEGRATED", "0")) | 
| Michael Walsh | 6cd9cbe | 2017-06-30 16:59:36 -0500 | [diff] [blame] | 150 |  | 
|  | 151 | if DEBUG_SKIP_INTEGRATED: | 
|  | 152 | return integrated_plug_ins_list | 
|  | 153 |  | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 154 | for plug_in_base_path in plug_in_base_path_list: | 
|  | 155 | # Get a list of all plug-in paths that support our mch_class. | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 156 | mch_class_candidate_list = glob.glob( | 
|  | 157 | plug_in_base_path + "*/supports_" + mch_class | 
|  | 158 | ) | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 159 | for candidate_path in mch_class_candidate_list: | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 160 | integrated_plug_in_dir_path = ( | 
|  | 161 | os.path.dirname(candidate_path) + os.sep | 
|  | 162 | ) | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 163 | integrated_file_path = integrated_plug_in_dir_path + "integrated" | 
|  | 164 | if os.path.exists(integrated_file_path): | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 165 | plug_in_name = os.path.basename( | 
|  | 166 | os.path.dirname(candidate_path) | 
|  | 167 | ) | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 168 | if plug_in_name not in integrated_plug_ins_list: | 
|  | 169 | # If this plug-in has not already been added to the list... | 
|  | 170 | integrated_plug_ins_list.append(plug_in_name) | 
|  | 171 |  | 
|  | 172 | return integrated_plug_ins_list | 
|  | 173 |  | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 174 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 175 | def return_plug_in_packages_list(plug_in_dir_paths, mch_class="obmc"): | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 176 | r""" | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 177 | Return a list of plug-in packages given the plug_in_dir_paths string.  This function calls | 
|  | 178 | validate_plug_in_package so it will fail if plug_in_dir_paths contains any invalid plug-ins. | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 179 |  | 
|  | 180 | Description of arguments: | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 181 | plug_in_dir_path                The "relative" or absolute path to a plug in package directory. | 
|  | 182 | mch_class                       The class of machine that we are testing (e.g. "op" = "open power", | 
|  | 183 | "obmc" = "open bmc", etc). | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 184 | """ | 
|  | 185 |  | 
|  | 186 | if plug_in_dir_paths != "": | 
|  | 187 | plug_in_packages_list = plug_in_dir_paths.split(":") | 
|  | 188 | else: | 
|  | 189 | plug_in_packages_list = [] | 
|  | 190 |  | 
|  | 191 | # Get a list of integrated plug-ins (w/o full path names). | 
|  | 192 | integrated_plug_ins_list = return_integrated_plug_ins(mch_class) | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 193 | # Put both lists together in plug_in_packages_list with no duplicates.  NOTE: This won't catch | 
|  | 194 | # duplicates if the caller specifies the full path name of a native plug-in but that should be rare | 
|  | 195 | # enough. | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 196 |  | 
|  | 197 | plug_in_packages_list = plug_in_packages_list + integrated_plug_ins_list | 
|  | 198 |  | 
| Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame] | 199 | plug_in_packages_list = list( | 
|  | 200 | set( | 
|  | 201 | [ | 
|  | 202 | validate_plug_in_package(path, mch_class) | 
|  | 203 | for path in plug_in_packages_list | 
|  | 204 | ] | 
|  | 205 | ) | 
|  | 206 | ) | 
| Michael Walsh | 7423c01 | 2016-10-04 10:27:21 -0500 | [diff] [blame] | 207 |  | 
|  | 208 | return plug_in_packages_list |