Whamcloud - gitweb
LU-10973 lnet: initial LUTF C infrastructure
[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 = false;
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 void 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;
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                         return;
80                 }
81
82                 /* update the LUTF internal database */
83                 PyRun_SimpleString("agents.reload()");
84                 PDEBUG("Agents reloaded. Dumping");
85                 PyRun_SimpleString("agents.dump()");
86
87                 if (g_lutf_cfg.script && strlen(g_lutf_cfg.script) > 0) {
88                         snprintf(buf, MAX_STR_LEN,
89                                  "suites['%s'].scripts['%s'].run()",
90                                  g_lutf_cfg.suite,
91                                  g_lutf_cfg.script);
92                 } else if (g_lutf_cfg.suite && strlen(g_lutf_cfg.suite) > 0) {
93                         snprintf(buf, MAX_STR_LEN,
94                                  "suites['%s'].run('%s')",
95                                  g_lutf_cfg.suite, pattern);
96                 } else {
97                         snprintf(buf, MAX_STR_LEN,
98                                  "suites.run('%s')", pattern);
99                 }
100                 PDEBUG("%s", buf);
101                 PyRun_SimpleString(buf);
102                 snprintf(buf, MAX_STR_LEN,
103                          "dumpGlobalTestResults('%s')", g_lutf_cfg.results_file);
104                 PDEBUG("%s", buf);
105                 PyRun_SimpleString(buf);
106                 PDEBUG("Shutting down the LUTF");
107                 PyRun_SimpleString("me.exit()");
108                 lutf_listener_shutdown();
109                 return;
110         } else if (g_lutf_cfg.shell == EN_LUTF_RUN_INTERACTIVE) {
111                 int rc;
112                 char *intro;
113
114                 PDEBUG("Running in Interactive mode");
115                 /*
116                  * start an independent shell
117                  * Since we imported all the necessary modules to start in
118                  * the main interpreter, copying the globals should copy
119                  * them in the interactive shell.
120                  */
121                 PyRun_SimpleString("vars = globals().copy()\n");
122                 PyRun_SimpleString("vars.update(locals())\n");
123                 PyRun_SimpleString("shell = code.InteractiveConsole(vars)\n");
124                 PyRun_SimpleString("shell.push('sys.ps1 = \"lutf>>> \"')\n");
125                 PyRun_SimpleString("shell.push('sys.ps2 = \"lutf... \"')\n");
126
127                 /* import base lutf module */
128                 g_py_inited = true;
129                 intro = "shell.interact(\"Welcome to the Lustre Unit Test Framework (LUTF)\\n\""
130                         "\"Convenience Functions: R() = dumpGlobalTestResults(), A() = agents.dump(), I() = me.dump_intfs(), X() = me.exit()\")";
131                 rc = PyRun_SimpleString(intro);
132                 if (rc)
133                         goto python_shutdown;
134         } else {
135                 /* run the telnet server. This becomes our main process
136                  * now
137                  */
138                 PDEBUG("Running in Daemon mode");
139                 sprintf(segment, "fname = os.path.join('%s', '%s')\n",
140                         g_lutf_cfg.lutf_path, OUT_PY_LOG);
141                 if (PyRun_SimpleString(segment)) {
142                         PERROR("Failed to create log file");
143                         goto python_shutdown;
144                 }
145                 sprintf(segment, "logfile = open(fname, 'w')\n");
146                 if (PyRun_SimpleString(segment)) {
147                         PERROR("Failed to open log file");
148                         goto python_shutdown;
149                 }
150                 if (PyRun_SimpleString("sys.stdout = sys.stderr = logfile\n")) {
151                         PERROR("Failed to redirect stdout and stderr");
152                         goto python_shutdown;
153                 }
154                 if (PyRun_SimpleString("from lutf_telnet_sr import LutfTelnetServer\n")) {
155                         PERROR("Failed to import LutfTelnetServer");
156                         goto python_shutdown;
157                 }
158                 sprintf(segment, "tns = LutfTelnetServer(%d)\n",
159                         g_lutf_cfg.l_info.hb_info.agent_telnet_port);
160                 if (PyRun_SimpleString(segment)) {
161                         PERROR("Failed to instantiate LutfTelnetServer");
162                         goto python_shutdown;
163                 }
164                 if (PyRun_SimpleString("tns.run()\n")) {
165                         PERROR("Failed to run LutfTelnetServer instance");
166                         goto python_shutdown;
167                 }
168                 if (PyRun_SimpleString("logfile.close()")) {
169                         PERROR("Failed to close logfile");
170                         goto python_shutdown;
171                 }
172 python_shutdown:
173                 PERROR("Exiting the python interpreter");
174         }
175         g_py_inited = false;
176         lutf_listener_shutdown();
177 }
178
179 /*
180  * gcc py.c -o py -I/usr/local/include/python2.7
181  * -L/usr/local/lib/python2.7/config -lm -ldl -lpthread -lutil -lpython2.7
182  */
183 lutf_rc_t python_init(void)
184 {
185         wchar_t program[5];
186
187         swprintf(program, 3, L"%hs", "lutf");
188
189         //char *path;
190         //char new_path[MAX_STR_LEN];
191         Py_SetProgramName(program);
192         //char *py_args[1];
193
194         //py_args[0] = argv[0];
195
196         Py_Initialize();
197
198         //sprintf(new_path, "%s:%s", path, script_path);
199         //PySys_SetPath(new_path);
200         //path = Py_GetPath();
201
202         python_run_interactive_shell();
203         PDEBUG("Python finalizing");
204
205         Py_Finalize();
206
207         PDEBUG("Python finalized");
208
209         return EN_LUTF_RC_OK;
210 }
211
212 lutf_rc_t python_handle_rpc_request(char *rpc)
213 {
214         lutf_rc_t rc = EN_LUTF_RC_OK;
215         PyGILState_STATE gstate;
216         PyObject *handle_rpc_req;
217         PyObject *lutf;
218         PyObject *me;
219         PyObject *str;
220         PyObject *args;
221         PyObject *result;
222
223         if (!g_py_inited)
224                 return EN_LUTF_RC_PY_SCRIPT_FAIL;
225
226         PDEBUG(rpc);
227
228         gstate = PyGILState_Ensure();
229
230         str = PyUnicode_FromString((char*)"lutf");
231         lutf = PyImport_Import(str);
232         me = PyObject_GetAttrString(lutf, (char*)"me");
233         handle_rpc_req = PyObject_GetAttrString(me, (char*)"handle_rpc_req");
234         args = PyTuple_Pack(1, PyUnicode_FromString(rpc));
235         result = PyObject_CallObject(handle_rpc_req, args);
236
237         if (!result)
238                 PDEBUG("handle_rpc_req() didn't return any values");
239
240         PyGILState_Release(gstate);
241
242         return rc;
243 }
244