Whamcloud - gitweb
20682c1e26961f1d727c8c7d9ab8ce608fb82d9e
[fs/lustre-release.git] / lustre / tests / lutf / src / lutf_python.c
1 #include <Python.h>
2 #include <netinet/in.h>
3 #include "lutf.h"
4 #include "lutf_python.h"
5 #include "lutf_listener.h"
6
7 extern lutf_config_params_t g_lutf_cfg;
8 bool g_py_inited;
9
10 static char *get_path_segment(char *path, int *len, char **more)
11 {
12         char *found = strchr(path, ':');
13         char *str = path;
14
15         if (!found) {
16                 *more = NULL;
17                 *len = strlen(str);
18                 return str;
19         }
20
21         *len = found - str;
22         if (*(found + 1) == '\n')
23                 *more = NULL;
24         else
25                 *more = found + 1;
26
27         return str;
28 }
29
30 static lutf_rc_t python_run_interactive_shell(void)
31 {
32         char buf[MAX_STR_LEN + 20];
33         char segment[MAX_STR_LEN];
34         char *seg;
35         char *more = g_lutf_cfg.py_path;
36         int len = 0;
37         lutf_rc_t rc = EN_LUTF_RC_OK;
38
39         PyRun_SimpleString("import code\n");
40         PyRun_SimpleString("import os\n");
41         PyRun_SimpleString("import sys\n");
42         PyRun_SimpleString("import readline\n");
43
44         /* all other paths are figured out within python */
45         snprintf(buf, MAX_STR_LEN,
46                 "sys.path.append(os.path.join('%s', 'python', 'infra'))",
47                 g_lutf_cfg.lutf_path);
48         PyRun_SimpleString(buf);
49
50         snprintf(buf, MAX_STR_LEN,
51                 "sys.path.append(\"%s/src\")\n",
52                 g_lutf_cfg.lutf_path);
53         PyRun_SimpleString(buf);
54
55         while (more != NULL) {
56                 seg = get_path_segment(more, &len, &more);
57                 snprintf(segment, len+1, "%s", seg);
58                 segment[len] = '\0';
59                 snprintf(buf, sizeof(buf),
60                         "sys.path.append(\"%s\")\n", segment);
61                 PyRun_SimpleString(buf);
62         }
63
64         PyRun_SimpleString("import lutf\n");
65         PyRun_SimpleString("from lutf import me,suites,"
66                            "agents,dumpGlobalTestResults,R,A,I,X\n");
67
68         g_py_inited = true;
69
70         if (g_lutf_cfg.shell == EN_LUTF_RUN_BATCH &&
71             g_lutf_cfg.l_info.type == EN_LUTF_MASTER) {
72                 char *pattern = g_lutf_cfg.pattern;
73
74                 PDEBUG("Running in Batch mode. Checking Agents are connected");
75
76                 rc = wait_for_agents(g_lutf_cfg.agents, 20);
77                 if (rc == EN_LUTF_RC_TIMEOUT) {
78                         PERROR("Not all agents connected. Aborting tests");
79                         lutf_listener_shutdown();
80                         return EN_LUTF_RC_TIMEOUT;
81                 }
82
83                 /* update the LUTF internal database */
84                 PyRun_SimpleString("agents.reload()");
85                 PDEBUG("Agents reloaded. Dumping");
86                 PyRun_SimpleString("agents.dump()");
87
88                 /* if a script is specified then a unique suite must be
89                  * specified as well.
90                  * if a suite_list is specified it takes precedence over
91                  * a single suite parameters. A pattern of scripts can be
92                  * provided to run matching scripts.
93                  * If a suite parameter is provided then run that
94                  * particular suite.
95                  * Otherwise just run everything.
96                  */
97                 if (g_lutf_cfg.script && strlen(g_lutf_cfg.script) > 0) {
98                         snprintf(buf, MAX_STR_LEN,
99                                  "suites['%s'].scripts['%s'].run()",
100                                  g_lutf_cfg.suite,
101                                  g_lutf_cfg.script);
102                 } else if (g_lutf_cfg.suite_list &&
103                            strlen(g_lutf_cfg.suite_list) > 0) {
104                         snprintf(buf, MAX_STR_LEN,
105                                  "suites.run(suite_list='%s', match='%s')",
106                                  g_lutf_cfg.suite_list, pattern);
107                 } else if (g_lutf_cfg.suite && strlen(g_lutf_cfg.suite) > 0) {
108                         snprintf(buf, MAX_STR_LEN,
109                                  "suites['%s'].run('%s')",
110                                  g_lutf_cfg.suite, pattern);
111                 } else {
112                         snprintf(buf, MAX_STR_LEN,
113                                  "suites.run(match='%s')", pattern);
114                 }
115                 PDEBUG("%s", buf);
116                 PyRun_SimpleString(buf);
117                 snprintf(buf, MAX_STR_LEN,
118                          "dumpGlobalTestResults('%s')", g_lutf_cfg.results_file);
119                 PDEBUG("%s", buf);
120                 PyRun_SimpleString(buf);
121                 PDEBUG("Shutting down the LUTF");
122                 PyRun_SimpleString("me.exit()");
123                 lutf_listener_shutdown();
124                 return EN_LUTF_RC_OK;
125         } else if (g_lutf_cfg.shell == EN_LUTF_RUN_INTERACTIVE) {
126                 int rc;
127                 char *intro;
128
129                 PDEBUG("Running in Interactive mode");
130                 /*
131                  * start an independent shell
132                  * Since we imported all the necessary modules to start in
133                  * the main interpreter, copying the globals should copy
134                  * them in the interactive shell.
135                  */
136                 PyRun_SimpleString("vars = globals().copy()\n");
137                 PyRun_SimpleString("vars.update(locals())\n");
138                 PyRun_SimpleString("shell = code.InteractiveConsole(vars)\n");
139                 PyRun_SimpleString("shell.push('sys.ps1 = \"lutf>>> \"')\n");
140                 PyRun_SimpleString("shell.push('sys.ps2 = \"lutf... \"')\n");
141
142                 /* import base lutf module */
143                 g_py_inited = true;
144                 intro = "shell.interact(\"Welcome to the Lustre Unit Test Framework (LUTF)\\n\""
145                         "\"Convenience Functions: R() = dumpGlobalTestResults(), A() = agents.dump(), I() = me.dump_intfs(), X() = me.exit()\")";
146                 rc = PyRun_SimpleString(intro);
147                 if (rc)
148                         goto python_shutdown;
149         } else {
150                 /* run the telnet server. This becomes our main process
151                  * now
152                  */
153                 PDEBUG("Running in Daemon mode");
154                 sprintf(segment, "fname = os.path.join('%s', '%s')\n",
155                         g_lutf_cfg.tmp_dir, OUT_PY_LOG);
156                 if (PyRun_SimpleString(segment)) {
157                         PERROR("Failed to create log file");
158                         rc = EN_LUTF_RC_FAIL;
159                         goto python_shutdown;
160                 }
161                 sprintf(segment, "logfile = open(fname, 'w')\n");
162                 if (PyRun_SimpleString(segment)) {
163                         PERROR("Failed to open log file");
164                         rc = EN_LUTF_RC_FAIL;
165                         goto python_shutdown;
166                 }
167                 if (PyRun_SimpleString("sys.stdout = sys.stderr = logfile\n")) {
168                         PERROR("Failed to redirect stdout and stderr");
169                         rc = EN_LUTF_RC_FAIL;
170                         goto python_shutdown;
171                 }
172                 if (PyRun_SimpleString("from lutf_telnet_sr import LutfTelnetServer\n")) {
173                         PERROR("Failed to import LutfTelnetServer");
174                         rc = EN_LUTF_RC_FAIL;
175                         goto python_shutdown;
176                 }
177                 sprintf(segment, "tns = LutfTelnetServer(%d)\n",
178                         g_lutf_cfg.l_info.hb_info.agent_telnet_port);
179                 if (PyRun_SimpleString(segment)) {
180                         PERROR("Failed to instantiate LutfTelnetServer");
181                         rc = EN_LUTF_RC_FAIL;
182                         goto python_shutdown;
183                 }
184                 if (PyRun_SimpleString("tns.run()\n")) {
185                         PERROR("Failed to run LutfTelnetServer instance");
186                         rc = EN_LUTF_RC_FAIL;
187                         goto python_shutdown;
188                 }
189                 if (PyRun_SimpleString("logfile.close()")) {
190                         PERROR("Failed to close logfile");
191                         rc = EN_LUTF_RC_FAIL;
192                         goto python_shutdown;
193                 }
194 python_shutdown:
195                 PERROR("Exiting the python interpreter");
196         }
197         g_py_inited = false;
198         lutf_listener_shutdown();
199
200         return rc;
201 }
202
203 /*
204  * gcc py.c -o py -I/usr/local/include/python2.7
205  * -L/usr/local/lib/python2.7/config -lm -ldl -lpthread -lutil -lpython2.7
206  */
207 lutf_rc_t python_init(void)
208 {
209         wchar_t program[5];
210         lutf_rc_t rc;
211
212         swprintf(program, 3, L"%hs", "lutf");
213
214         //char *path;
215         //char new_path[MAX_STR_LEN];
216         Py_SetProgramName(program);
217         //char *py_args[1];
218
219         //py_args[0] = argv[0];
220
221         Py_Initialize();
222
223         //sprintf(new_path, "%s:%s", path, script_path);
224         //PySys_SetPath(new_path);
225         //path = Py_GetPath();
226
227         rc = python_run_interactive_shell();
228         PDEBUG("Python finalizing");
229
230         Py_Finalize();
231
232         PDEBUG("Python finalized");
233
234         return rc;
235 }
236
237 lutf_rc_t python_handle_rpc_request(char *rpc)
238 {
239         lutf_rc_t rc = EN_LUTF_RC_OK;
240         PyGILState_STATE gstate;
241         PyObject *handle_rpc_req;
242         PyObject *lutf;
243         PyObject *me;
244         PyObject *str;
245         PyObject *args;
246         PyObject *result;
247
248         if (!g_py_inited)
249                 return EN_LUTF_RC_PY_SCRIPT_FAIL;
250
251         PDEBUG(rpc);
252
253         gstate = PyGILState_Ensure();
254
255         str = PyUnicode_FromString((char *)"lutf");
256         lutf = PyImport_Import(str);
257         me = PyObject_GetAttrString(lutf, (char *)"me");
258         handle_rpc_req = PyObject_GetAttrString(me, (char *)"handle_rpc_req");
259         args = PyTuple_Pack(1, PyUnicode_FromString(rpc));
260         result = PyObject_CallObject(handle_rpc_req, args);
261
262         if (!result)
263                 PDEBUG("handle_rpc_req() didn't return any values");
264
265         PyGILState_Release(gstate);
266
267         return rc;
268 }
269