Merge lp:~xnox/upstart/cgroup-states into lp:~jamesodhunt/upstart/cgroups

Proposed by Dimitri John Ledkov
Status: Work in progress
Proposed branch: lp:~xnox/upstart/cgroup-states
Merge into: lp:~jamesodhunt/upstart/cgroups
Diff against target: 1234 lines (+343/-197)
10 files modified
init/job.c (+1/-11)
init/job_process.c (+17/-82)
init/tests/test_event.c (+6/-6)
init/tests/test_job.c (+72/-34)
scripts/Makefile.am (+9/-9)
scripts/pyupstart.py (+102/-4)
scripts/tests/test_pyupstart_cgmanager.py (+63/-0)
scripts/tests/test_pyupstart_session_init.py (+0/-26)
scripts/tests/test_pyupstart_system_cgroups.py (+73/-0)
scripts/tests/test_pyupstart_system_init.py (+0/-25)
To merge this branch: bzr merge lp:~xnox/upstart/cgroup-states
Reviewer Review Type Date Requested Status
James Hunt Pending
Review via email: mp+214514@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Dimitri John Ledkov (xnox) wrote :

This fixes a bunch of test_job and test_job_process test suite failures. Mostly it's adjusting state expectations in the test-suite, but also fixes JOB_PRE_STOP_SETUP -> JOB_PRE_STOP transition and updates the asserts in the job_process (once we are in the process failure handler, the relevant process has completed the setup and thus is in the "full" state, as far as I understand it)

lp:~xnox/upstart/cgroup-states updated
1605. By Dimitri John Ledkov

Actually, it looks like the tests might be broken.

1606. By Dimitri John Ledkov

Extend asserts to setup stages

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

so running under cgmanager in a container i notice that jobs do not progress from *_SETUP -> * states.
Also process tracking with e.g. expect stop did not work it seems (well, i've kill -s CONT a few processes to get the container booting)

I am now leaning to believe that stats in job_process.c (e.g. PROCESS_PRE_STOP) should assert state JOB_PRE_STOP. And that it's buggy behavior for jobs to get stuck in _SETUP state and not transition to the full one. (when cgroups stanza is specified that is)

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

I've tested all but "security" and "pre-stop" processes and they all get cgroups containment now.

lp:~xnox/upstart/cgroup-states updated
1607. By Dimitri John Ledkov

We need to both SIGCONT & switch to next state for 'expect stop' and setup states.

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

With -r1607 i get correct transitions from *_SETUP -> * states.

However, expect stop jobs are still stuck in "setup" and do not transition to running. Investigating.

lp:~xnox/upstart/cgroup-states updated
1608. By Dimitri John Ledkov

SIGCONT in setup as well.

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

Now the states progress to quickly, e.g. we jump to spawning the main process and running, ahead of pre-start process completing, if and only if cgroups stanza is specified in the job.

lp:~xnox/upstart/cgroup-states updated
1609. By Dimitri John Ledkov

Merge pythonic CGManager

1610. By Dimitri John Ledkov

Add pyupstart CGManager tests

1611. By Dimitri John Ledkov

And kaboom!

Unmerged revisions

1611. By Dimitri John Ledkov

And kaboom!

1610. By Dimitri John Ledkov

Add pyupstart CGManager tests

1609. By Dimitri John Ledkov

Merge pythonic CGManager

1608. By Dimitri John Ledkov

SIGCONT in setup as well.

1607. By Dimitri John Ledkov

We need to both SIGCONT & switch to next state for 'expect stop' and setup states.

1606. By Dimitri John Ledkov

Extend asserts to setup stages

1605. By Dimitri John Ledkov

Actually, it looks like the tests might be broken.

1604. By Dimitri John Ledkov

Fix up cgroup-states.

1603. By Dimitri John Ledkov

Remove debug

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'init/job.c'
2--- init/job.c 2014-04-04 18:42:18 +0000
3+++ init/job.c 2014-04-08 20:51:56 +0000
4@@ -278,8 +278,6 @@
5 {
6 nih_assert (job != NULL);
7
8- nih_message ("XXX:%s:%d: ", __func__, __LINE__);
9-
10 if (job->goal == goal)
11 return;
12
13@@ -348,9 +346,6 @@
14 {
15 nih_assert (job != NULL);
16
17- nih_message ("XXX:%s:%d:job '%s': goal=%s, state=%s, new state=%s", __func__, __LINE__,
18- job_name (job), job_goal_name (job->goal), job_state_name (job->state), job_state_name (state));
19-
20 while (job->state != state) {
21 JobState old_state;
22 int unused;
23@@ -363,9 +358,6 @@
24 old_state = job->state;
25 job->state = state;
26
27- nih_message ("XXX:%s:%d:job '%s': goal=%s, state=%s, old state=%s", __func__, __LINE__,
28- job_name (job), job_goal_name (job->goal), job_state_name (job->state), job_state_name (old_state));
29-
30 NIH_LIST_FOREACH (control_conns, iter) {
31 NihListEntry *entry = (NihListEntry *)iter;
32 DBusConnection *conn = (DBusConnection *)entry->data;
33@@ -673,8 +665,6 @@
34 {
35 nih_assert (job != NULL);
36
37- nih_message ("XXX:%s:%d: ", __func__, __LINE__);
38-
39 switch (job->state) {
40 case JOB_WAITING:
41 switch (job->goal) {
42@@ -789,7 +779,7 @@
43 case JOB_PRE_STOP_SETUP:
44 switch (job->goal) {
45 case JOB_STOP:
46- return JOB_STOPPING;
47+ return JOB_PRE_STOP;
48 case JOB_START:
49 return JOB_PRE_STOP;
50 case JOB_RESPAWN:
51
52=== modified file 'init/job_process.c'
53--- init/job_process.c 2014-04-04 18:42:18 +0000
54+++ init/job_process.c 2014-04-08 20:51:56 +0000
55@@ -199,8 +199,6 @@
56
57 nih_assert (job != NULL);
58
59- nih_message ("XXX:%s:%d: ", __func__, __LINE__);
60-
61 proc = job->class->process[process];
62 nih_assert (proc != NULL);
63 nih_assert (proc->command != NULL);
64@@ -449,8 +447,6 @@
65 int cgroups_needed = FALSE;
66 #endif /* ENABLE_CGROUPS */
67
68- //nih_message ("XXX:%s:%d: ", __func__, __LINE__);
69-
70 nih_assert (job != NULL);
71 nih_assert (job->class != NULL);
72 nih_assert (job->log != NULL);
73@@ -950,11 +946,8 @@
74 /* Signal to parent that the (final) setup phase
75 * is complete.
76 */
77- nih_message ("XXX:%s:%d: raising SIGSTOP to %s process %s pid %d (state=%s)", __func__, __LINE__,
78- job_name (job), process_name (process), getpid(), job_state_name (job->state));fflush (NULL);
79 raise (SIGSTOP);
80 }
81- nih_message ("XXX:%s:%d: ", __func__, __LINE__);
82
83 #endif /* ENABLE_CGROUPS */
84
85@@ -964,14 +957,11 @@
86 job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SETGID, 0);
87 }
88
89- nih_message ("XXX:%s:%d: ", __func__, __LINE__);
90 if (job_setuid != (uid_t)-1 && setuid (job_setuid) < 0) {
91 nih_error_raise_system ();
92 job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SETUID, 0);
93 }
94- nih_message ("XXX:%s:%d: ", __func__, __LINE__);
95 }
96- nih_message ("XXX:%s:%d: ", __func__, __LINE__);
97
98 /* Reset all the signal handlers back to their default handling so
99 * the child isn't unexpectedly ignoring any, and so we won't
100@@ -980,7 +970,6 @@
101 nih_signal_reset ();
102 sigprocmask (SIG_SETMASK, &orig_set, NULL);
103
104- nih_message ("XXX:%s:%d: ", __func__, __LINE__);
105 /* Notes:
106 *
107 * - we can't use pause() here since there would then be no way to
108@@ -1003,7 +992,6 @@
109 close (fds[1]);
110 raise (SIGSTOP);
111 }
112- nih_message ("XXX:%s:%d: ", __func__, __LINE__);
113
114 #ifdef ENABLE_CGROUPS
115 /* Move the pid into the appropriate cgroups now that
116@@ -1022,17 +1010,14 @@
117 }
118 #endif /* ENABLE_CGROUPS */
119
120- nih_message ("XXX:%s:%d: ", __func__, __LINE__);
121 /* Set up a process trace if we need to trace forks */
122 if (trace) {
123- nih_message ("XXX:%s:%d: ", __func__, __LINE__);
124 if (ptrace (PTRACE_TRACEME, 0, NULL, 0) < 0) {
125 nih_error_raise_system();
126 job_process_error_abort (fds[1],
127 JOB_PROCESS_ERROR_PTRACE, 0);
128 }
129 }
130- nih_message ("XXX:%s:%d: ", __func__, __LINE__);
131
132 /* Execute the process, if we escape from here it failed */
133 if (execvp (argv[0], argv) < 0) {
134@@ -1526,9 +1511,6 @@
135
136 nih_assert (pid > 0);
137
138- nih_message ("XXX:%s:%d:pid=%d, event=%x, status=%d", __func__, __LINE__,
139- pid, event, status);
140-
141 /* Find the job that an event ocurred for, and identify which of the
142 * job's process it was. If we don't know about it, then we simply
143 * ignore the event.
144@@ -1537,9 +1519,6 @@
145 if (! job)
146 return;
147
148- nih_message ("XXX:%s:%d:job '%s': goal=%s, state=%s", __func__, __LINE__,
149- job_name (job), job_goal_name (job->goal), job_state_name (job->state));
150-
151 /* Check the job's normal exit clauses to see whether this is a failure
152 * worth warning about.
153 */
154@@ -1553,7 +1532,6 @@
155
156 switch (event) {
157 case NIH_CHILD_EXITED:
158- nih_message ("XXX:%s:%d:", __func__, __LINE__);
159 /* Child exited; check status to see whether it exited
160 * normally (zero) or with a non-zero status.
161 */
162@@ -1571,7 +1549,6 @@
163 break;
164 case NIH_CHILD_KILLED:
165 case NIH_CHILD_DUMPED:
166- nih_message ("XXX:%s:%d:", __func__, __LINE__);
167 /* Child was killed by a signal, and maybe dumped core. We
168 * store the signal value in the higher byte of status (it's
169 * safe to do that) to distinguish it from a normal exit
170@@ -1592,7 +1569,6 @@
171 job_process_terminated (job, process, status);
172 break;
173 case NIH_CHILD_STOPPED:
174- nih_message ("XXX:%s:%d:", __func__, __LINE__);
175 /* Child was stopped by a signal, make sure it was SIGSTOP
176 * and not a tty-related signal.
177 */
178@@ -1608,13 +1584,11 @@
179 }
180
181 if (status == SIGSTOP) {
182- nih_message ("XXX:%s:%d:", __func__, __LINE__);
183 job_process_stopped (job, process);
184 }
185
186 break;
187 case NIH_CHILD_CONTINUED:
188- nih_message ("XXX:%s:%d:", __func__, __LINE__);
189 /* Child was continued by a signal.
190 */
191 sig = nih_signal_to_name (status);
192@@ -1629,7 +1603,6 @@
193 }
194 break;
195 case NIH_CHILD_TRAPPED:
196- nih_message ("XXX:%s:%d:", __func__, __LINE__);
197 /* Child received a signal while we were tracing it. This
198 * can be a signal raised inside the kernel as a side-effect
199 * of the trace because the child called fork() or exec();
200@@ -1637,29 +1610,23 @@
201 */
202 if ((job->trace_state == TRACE_NEW)
203 && (status == SIGTRAP)) {
204- nih_message ("XXX:%s:%d:", __func__, __LINE__);
205 job_process_trace_new (job, process);
206 } else if ((job->trace_state == TRACE_NEW_CHILD)
207 && (status == SIGSTOP)) {
208- nih_message ("XXX:%s:%d:", __func__, __LINE__);
209 job_process_trace_new_child (job, process);
210 } else {
211- nih_message ("XXX:%s:%d:", __func__, __LINE__);
212 job_process_trace_signal (job, process, status);
213 }
214 break;
215 case NIH_CHILD_PTRACE:
216- nih_message ("XXX:%s:%d:", __func__, __LINE__);
217 /* Child called an important syscall that can modify the
218 * state of the process trace we hold.
219 */
220 switch (status) {
221 case PTRACE_EVENT_FORK:
222- nih_message ("XXX:%s:%d:", __func__, __LINE__);
223 job_process_trace_fork (job, process);
224 break;
225 case PTRACE_EVENT_EXEC:
226- nih_message ("XXX:%s:%d:", __func__, __LINE__);
227 job_process_trace_exec (job, process);
228 break;
229 default:
230@@ -1697,10 +1664,6 @@
231
232 nih_assert (job != NULL);
233
234- nih_message ("XXX:%s:%d:job '%s': goal=%s, state=%s, process=%s, status=%d", __func__, __LINE__,
235- job_name (job), job_goal_name (job->goal), job_state_name (job->state),
236- process_name (process), status);
237-
238 switch (process) {
239 case PROCESS_MAIN:
240 nih_assert ((job->state == JOB_RUNNING)
241@@ -1708,7 +1671,9 @@
242 || (job->state == JOB_KILLED)
243 || (job->state == JOB_STOPPING)
244 || (job->state == JOB_POST_START)
245+ || (job->state == JOB_POST_START_SETUP)
246 || (job->state == JOB_PRE_STOP)
247+ || (job->state == JOB_PRE_STOP_SETUP)
248 || (job->state == JOB_SETUP));
249
250 /* We don't change the state if we're in post-start and there's
251@@ -1800,7 +1765,8 @@
252 stop = TRUE;
253 break;
254 case PROCESS_SECURITY:
255- nih_assert (job->state == JOB_SECURITY_SETUP);
256+ nih_assert ((job->state == JOB_SECURITY)
257+ || (job->state == JOB_SECURITY_SETUP));
258
259 /* We should always fail the job if the security profile
260 * failed to load
261@@ -1811,7 +1777,8 @@
262 }
263 break;
264 case PROCESS_PRE_START:
265- nih_assert (job->state == JOB_PRE_START_SETUP);
266+ nih_assert ((job->state == JOB_PRE_START)
267+ || (job->state == JOB_PRE_START_SETUP));
268
269 /* If the pre-start script is killed or exits with a status
270 * other than zero, it's always considered a failure since
271@@ -1823,7 +1790,8 @@
272 }
273 break;
274 case PROCESS_POST_START:
275- nih_assert (job->state == JOB_POST_START_SETUP);
276+ nih_assert ((job->state == JOB_POST_START)
277+ || (job->state == JOB_POST_START_SETUP));
278
279 /* We always want to change the state when the post-start
280 * script terminates; if the main process is running, we'll
281@@ -1834,7 +1802,8 @@
282 */
283 break;
284 case PROCESS_PRE_STOP:
285- nih_assert (job->state == JOB_PRE_STOP_SETUP);
286+ nih_assert ((job->state == JOB_PRE_STOP)
287+ || (job->state == JOB_PRE_STOP_SETUP));
288
289 /* We always want to change the state when the pre-stop
290 * script terminates, we either want to go back into running
291@@ -1845,7 +1814,8 @@
292 */
293 break;
294 case PROCESS_POST_STOP:
295- nih_assert (job->state == JOB_POST_STOP_SETUP);
296+ nih_assert ((job->state == JOB_POST_STOP)
297+ || (job->state == JOB_POST_STOP_SETUP));
298
299 /* If the post-stop script is killed or exits with a status
300 * other than zero, it's always considered a failure since
301@@ -2022,34 +1992,19 @@
302 break;
303 }
304
305- nih_message ("XXX:%s:%d: job=%s, process=%s, pid %d (state=%s, goal=%s)", __func__, __LINE__,
306- job_name (job), process_name (process), job->pid[process], job_state_name (job->state), job_goal_name (job->goal));
307-
308 /* Any process can stop on a signal, but we only care about the
309 * main process when the state is still spawned and any jobs
310 * which require (cgroup) setup.
311- */
312- if (! ((process == PROCESS_MAIN && job->state == JOB_SPAWNED) || setup))
313- return;
314-
315- /* Send SIGCONT back and change the state to the next one for
316+ *
317+ * Send SIGCONT back and change the state to the next one for
318 * 'expect stop' jobs and those that require cgroup setup.
319 */
320- if (job->class->expect == EXPECT_STOP || (job_needs_cgroups (job) && setup)) {
321- nih_message ("XXX:%s:%d: sending SIGCONT to %s process %s pid %d (state=%s)", __func__, __LINE__,
322- job_name (job), process_name (process), job->pid[process], job_state_name (job->state));
323-
324+ if (job->class->expect == EXPECT_STOP && process == PROCESS_MAIN
325+ && (job->state == JOB_SETUP || job->state == JOB_SPAWNED)
326+ || (job_needs_cgroups (job) && setup)) {
327 kill (job->pid[process], SIGCONT);
328- }
329-
330- if (job->class->expect == EXPECT_STOP && process == PROCESS_MAIN && job->state == JOB_SPAWNED) {
331- nih_message ("XXX:%s:%d: changing state for job %s process %s pid %d (state=%s)", __func__, __LINE__,
332- job_name (job), process_name (process), job->pid[process], job_state_name (job->state));
333-
334 job_change_state (job, job_next_state (job));
335 }
336-
337- nih_message ("XXX:%s:%d: ", __func__, __LINE__);
338 }
339
340
341@@ -2072,10 +2027,6 @@
342 nih_assert ((job->trace_state == TRACE_NEW)
343 || (job->trace_state == TRACE_NEW_CHILD));
344
345- nih_message ("XXX:%s:%d:job '%s': goal=%s, state=%s, process=%s", __func__, __LINE__,
346- job_name (job), job_goal_name (job->goal), job_state_name (job->state),
347- process_name (process));
348-
349 /* Any process can get us to trace them, but we only care about the
350 * main process when the state is still spawned.
351 */
352@@ -2127,10 +2078,6 @@
353 nih_assert (job != NULL);
354 nih_assert (job->trace_state == TRACE_NEW_CHILD);
355
356- nih_message ("XXX:%s:%d:job '%s': goal=%s, state=%s, process=%s", __func__, __LINE__,
357- job_name (job), job_goal_name (job->goal), job_state_name (job->state),
358- process_name (process));
359-
360 /* Any process can get us to trace them, but we only care about the
361 * main process when the state is still spawned.
362 */
363@@ -2176,10 +2123,6 @@
364 {
365 nih_assert (job != NULL);
366
367- nih_message ("XXX:%s:%d:job '%s': goal=%s, state=%s, process=%s, signum=%d", __func__, __LINE__,
368- job_name (job), job_goal_name (job->goal), job_state_name (job->state),
369- process_name (process), signum);
370-
371 /* Any process can get us to trace them, but we only care about the
372 * main process when the state is still spawned.
373 */
374@@ -2215,10 +2158,6 @@
375
376 nih_assert (job != NULL);
377
378- nih_message ("XXX:%s:%d:job '%s': goal=%s, state=%s, process=%s", __func__, __LINE__,
379- job_name (job), job_goal_name (job->goal), job_state_name (job->state),
380- process_name (process));
381-
382 /* Any process can get us to trace them, but we only care about the
383 * main process when the state is still spawned.
384 */
385@@ -2287,10 +2226,6 @@
386 {
387 nih_assert (job != NULL);
388
389- nih_message ("XXX:%s:%d:job '%s': goal=%s, state=%s, process=%s", __func__, __LINE__,
390- job_name (job), job_goal_name (job->goal), job_state_name (job->state),
391- process_name (process));
392-
393 /* Any process can get us to trace them, but we only care about the
394 * main process when the state is still spawned and we're tracing it.
395 */
396
397=== modified file 'init/tests/test_event.c'
398--- init/tests/test_event.c 2013-01-31 17:23:55 +0000
399+++ init/tests/test_event.c 2014-04-08 20:51:56 +0000
400@@ -1259,7 +1259,7 @@
401 job = (Job *)nih_hash_lookup (class->instances, "");
402
403 TEST_EQ (job->goal, JOB_STOP);
404- TEST_EQ (job->state, JOB_POST_STOP);
405+ TEST_EQ (job->state, JOB_POST_STOP_SETUP);
406
407 TEST_GT (job->pid[PROCESS_POST_STOP], 0);
408 waitpid (job->pid[PROCESS_POST_STOP], NULL, 0);
409@@ -1335,7 +1335,7 @@
410 job = (Job *)nih_hash_lookup (class->instances, "");
411
412 TEST_EQ (job->goal, JOB_STOP);
413- TEST_EQ (job->state, JOB_POST_STOP);
414+ TEST_EQ (job->state, JOB_POST_STOP_SETUP);
415
416 TEST_GT (job->pid[PROCESS_POST_STOP], 0);
417 waitpid (job->pid[PROCESS_POST_STOP], NULL, 0);
418@@ -1439,7 +1439,7 @@
419 job = (Job *)nih_hash_lookup (class->instances, "");
420
421 TEST_EQ (job->goal, JOB_STOP);
422- TEST_EQ (job->state, JOB_POST_STOP);
423+ TEST_EQ (job->state, JOB_POST_STOP_SETUP);
424
425 TEST_GT (job->pid[PROCESS_POST_STOP], 0);
426 waitpid (job->pid[PROCESS_POST_STOP], NULL, 0);
427@@ -1621,7 +1621,7 @@
428 job = (Job *)nih_hash_lookup (class->instances, "");
429
430 TEST_EQ (job->goal, JOB_STOP);
431- TEST_EQ (job->state, JOB_POST_STOP);
432+ TEST_EQ (job->state, JOB_POST_STOP_SETUP);
433
434 TEST_GT (job->pid[PROCESS_POST_STOP], 0);
435 waitpid (job->pid[PROCESS_POST_STOP], NULL, 0);
436@@ -1980,7 +1980,7 @@
437 event_poll ();
438
439 TEST_EQ (job->goal, JOB_STOP);
440- TEST_EQ (job->state, JOB_POST_STOP);
441+ TEST_EQ (job->state, JOB_POST_STOP_SETUP);
442 TEST_GT (job->pid[PROCESS_POST_STOP], 0);
443 TEST_EQ_P (job->blocker, NULL);
444
445@@ -2026,7 +2026,7 @@
446 event_poll ();
447
448 TEST_EQ (job->goal, JOB_START);
449- TEST_EQ (job->state, JOB_PRE_START);
450+ TEST_EQ (job->state, JOB_PRE_START_SETUP);
451 TEST_GT (job->pid[PROCESS_PRE_START], 0);
452 TEST_EQ_P (job->blocker, NULL);
453
454
455=== modified file 'init/tests/test_job.c'
456--- init/tests/test_job.c 2013-11-18 16:38:32 +0000
457+++ init/tests/test_job.c 2014-04-08 20:51:56 +0000
458@@ -1059,10 +1059,10 @@
459 job->failed_process = PROCESS_INVALID;
460 job->exit_status = 0;
461
462- job_change_state (job, JOB_PRE_START);
463+ job_change_state (job, JOB_PRE_START_SETUP);
464
465 TEST_EQ (job->goal, JOB_START);
466- TEST_EQ (job->state, JOB_PRE_START);
467+ TEST_EQ (job->state, JOB_PRE_START_SETUP);
468 TEST_NE (job->pid[PROCESS_PRE_START], 0);
469
470 waitpid (job->pid[PROCESS_PRE_START], &status, 0);
471@@ -1125,7 +1125,7 @@
472 job->failed_process = PROCESS_INVALID;
473 job->exit_status = 0;
474
475- job_change_state (job, JOB_PRE_START);
476+ job_change_state (job, JOB_PRE_START_SETUP);
477
478 TEST_EQ (job->goal, JOB_START);
479 TEST_EQ (job->state, JOB_RUNNING);
480@@ -1200,7 +1200,7 @@
481 job->exit_status = 0;
482
483 TEST_DIVERT_STDERR (output) {
484- job_change_state (job, JOB_PRE_START);
485+ job_change_state (job, JOB_PRE_START_SETUP);
486 }
487 rewind (output);
488
489@@ -1284,7 +1284,7 @@
490 job->failed_process = PROCESS_INVALID;
491 job->exit_status = 0;
492
493- job_change_state (job, JOB_SPAWNED);
494+ job_change_state (job, JOB_SETUP);
495
496 TEST_EQ (job->goal, JOB_START);
497 TEST_EQ (job->state, JOB_RUNNING);
498@@ -1352,7 +1352,7 @@
499 job->failed_process = PROCESS_INVALID;
500 job->exit_status = 0;
501
502- job_change_state (job, JOB_SPAWNED);
503+ job_change_state (job, JOB_SETUP);
504
505 TEST_EQ (job->goal, JOB_START);
506 TEST_EQ (job->state, JOB_RUNNING);
507@@ -1432,7 +1432,7 @@
508 job->failed_process = PROCESS_INVALID;
509 job->exit_status = 0;
510
511- job_change_state (job, JOB_SPAWNED);
512+ job_change_state (job, JOB_SETUP);
513
514 TEST_EQ (job->goal, JOB_START);
515 TEST_EQ (job->state, JOB_RUNNING);
516@@ -1507,7 +1507,7 @@
517 job->failed_process = PROCESS_INVALID;
518 job->exit_status = 0;
519
520- job_change_state (job, JOB_SPAWNED);
521+ job_change_state (job, JOB_SETUP);
522
523 TEST_EQ (job->goal, JOB_START);
524 TEST_EQ (job->state, JOB_RUNNING);
525@@ -1572,7 +1572,7 @@
526 job->exit_status = 0;
527
528 TEST_DIVERT_STDERR (output) {
529- job_change_state (job, JOB_SPAWNED);
530+ job_change_state (job, JOB_SETUP);
531 }
532 rewind (output);
533
534@@ -1658,10 +1658,10 @@
535 job->failed_process = PROCESS_INVALID;
536 job->exit_status = 0;
537
538- job_change_state (job, JOB_SPAWNED);
539+ job_change_state (job, JOB_SETUP);
540
541 TEST_EQ (job->goal, JOB_START);
542- TEST_EQ (job->state, JOB_SPAWNED);
543+ TEST_EQ (job->state, JOB_SETUP);
544 TEST_NE (job->pid[PROCESS_MAIN], 0);
545
546 waitpid (job->pid[PROCESS_MAIN], &status, 0);
547@@ -1727,10 +1727,10 @@
548 job->failed_process = PROCESS_INVALID;
549 job->exit_status = 0;
550
551- job_change_state (job, JOB_POST_START);
552+ job_change_state (job, JOB_POST_START_SETUP);
553
554 TEST_EQ (job->goal, JOB_START);
555- TEST_EQ (job->state, JOB_POST_START);
556+ TEST_EQ (job->state, JOB_POST_START_SETUP);
557 TEST_EQ (job->pid[PROCESS_MAIN], 1);
558 TEST_NE (job->pid[PROCESS_POST_START], 0);
559
560@@ -1794,7 +1794,7 @@
561 job->failed_process = PROCESS_INVALID;
562 job->exit_status = 0;
563
564- job_change_state (job, JOB_POST_START);
565+ job_change_state (job, JOB_POST_START_SETUP);
566
567 TEST_EQ (job->goal, JOB_START);
568 TEST_EQ (job->state, JOB_RUNNING);
569@@ -1858,7 +1858,7 @@
570 job->exit_status = 0;
571
572 TEST_DIVERT_STDERR (output) {
573- job_change_state (job, JOB_POST_START);
574+ job_change_state (job, JOB_POST_START_SETUP);
575 }
576 rewind (output);
577
578@@ -2058,10 +2058,10 @@
579 job->failed_process = PROCESS_INVALID;
580 job->exit_status = 0;
581
582- job_change_state (job, JOB_PRE_STOP);
583+ job_change_state (job, JOB_PRE_STOP_SETUP);
584
585 TEST_EQ (job->goal, JOB_STOP);
586- TEST_EQ (job->state, JOB_PRE_STOP);
587+ TEST_EQ (job->state, JOB_PRE_STOP_SETUP);
588 TEST_EQ (job->pid[PROCESS_MAIN], 1);
589 TEST_NE (job->pid[PROCESS_PRE_STOP], 0);
590
591@@ -2125,7 +2125,7 @@
592 job->failed_process = PROCESS_INVALID;
593 job->exit_status = 0;
594
595- job_change_state (job, JOB_PRE_STOP);
596+ job_change_state (job, JOB_PRE_STOP_SETUP);
597
598 TEST_EQ (job->goal, JOB_STOP);
599 TEST_EQ (job->state, JOB_STOPPING);
600@@ -2198,7 +2198,7 @@
601 job->failed_process = PROCESS_INVALID;
602 job->exit_status = 0;
603
604- job_change_state (job, JOB_PRE_STOP);
605+ job_change_state (job, JOB_PRE_STOP_SETUP);
606
607 TEST_EQ (job->goal, JOB_STOP);
608 TEST_EQ (job->state, JOB_STOPPING);
609@@ -2283,7 +2283,7 @@
610 job->failed_process = PROCESS_INVALID;
611 job->exit_status = 0;
612
613- job_change_state (job, JOB_PRE_STOP);
614+ job_change_state (job, JOB_PRE_STOP_SETUP);
615
616 TEST_EQ (job->goal, JOB_STOP);
617 TEST_EQ (job->state, JOB_STOPPING);
618@@ -2364,7 +2364,7 @@
619 job->exit_status = 0;
620
621 TEST_DIVERT_STDERR (output) {
622- job_change_state (job, JOB_PRE_STOP);
623+ job_change_state (job, JOB_PRE_STOP_SETUP);
624 }
625 rewind (output);
626
627@@ -3039,7 +3039,7 @@
628 job_change_state (job, JOB_KILLED);
629
630 TEST_EQ (job->goal, JOB_STOP);
631- TEST_EQ (job->state, JOB_POST_STOP);
632+ TEST_EQ (job->state, JOB_POST_STOP_SETUP);
633 TEST_NE (job->pid[PROCESS_POST_STOP], 0);
634
635 waitpid (job->pid[PROCESS_POST_STOP], &status, 0);
636@@ -3100,10 +3100,10 @@
637 job->failed_process = PROCESS_INVALID;
638 job->exit_status = 0;
639
640- job_change_state (job, JOB_POST_STOP);
641+ job_change_state (job, JOB_POST_STOP_SETUP);
642
643 TEST_EQ (job->goal, JOB_STOP);
644- TEST_EQ (job->state, JOB_POST_STOP);
645+ TEST_EQ (job->state, JOB_POST_STOP_SETUP);
646 TEST_NE (job->pid[PROCESS_POST_STOP], 0);
647
648 waitpid (job->pid[PROCESS_POST_STOP], &status, 0);
649@@ -3168,7 +3168,7 @@
650
651 TEST_FREE_TAG (job);
652
653- job_change_state (job, JOB_POST_STOP);
654+ job_change_state (job, JOB_POST_STOP_SETUP);
655
656 TEST_FREE (job);
657
658@@ -3228,7 +3228,7 @@
659 TEST_FREE_TAG (job);
660
661 TEST_DIVERT_STDERR (output) {
662- job_change_state (job, JOB_POST_STOP);
663+ job_change_state (job, JOB_POST_STOP_SETUP);
664 }
665 rewind (output);
666
667@@ -4000,11 +4000,20 @@
668
669
670 /* Check that the next state if we're starting a starting job is
671+ * security setup.
672+ */
673+ TEST_FEATURE ("with starting job and a goal of start");
674+ job->goal = JOB_START;
675+ job->state = JOB_STARTING;
676+
677+ TEST_EQ (job_next_state (job), JOB_SECURITY_SETUP);
678+
679+ /* Check that the next state if we're starting a security job is
680 * security.
681 */
682- TEST_FEATURE ("with starting job and a goal of start");
683+ TEST_FEATURE ("with security job and a goal of start");
684 job->goal = JOB_START;
685- job->state = JOB_STARTING;
686+ job->state = JOB_SECURITY_SETUP;
687
688 TEST_EQ (job_next_state (job), JOB_SECURITY);
689
690@@ -4015,7 +4024,7 @@
691 job->goal = JOB_START;
692 job->state = JOB_SECURITY;
693
694- TEST_EQ (job_next_state (job), JOB_PRE_START);
695+ TEST_EQ (job_next_state (job), JOB_PRE_START_SETUP);
696
697 /* Check that the next state if we're stopping an security job is
698 * stopping.
699@@ -4037,11 +4046,20 @@
700
701
702 /* Check that the next state if we're starting a pre-start job is
703+ * setup.
704+ */
705+ TEST_FEATURE ("with pre-start job and a goal of start");
706+ job->goal = JOB_START;
707+ job->state = JOB_PRE_START;
708+
709+ TEST_EQ (job_next_state (job), JOB_SETUP);
710+
711+ /* Check that the next state if we're starting a pre-start job is
712 * spawned.
713 */
714 TEST_FEATURE ("with pre-start job and a goal of start");
715 job->goal = JOB_START;
716- job->state = JOB_PRE_START;
717+ job->state = JOB_SETUP;
718
719 TEST_EQ (job_next_state (job), JOB_SPAWNED);
720
721@@ -4057,11 +4075,20 @@
722
723
724 /* Check that the next state if we're starting a spawned job is
725+ * post-start setup.
726+ */
727+ TEST_FEATURE ("with spawned job and a goal of start");
728+ job->goal = JOB_START;
729+ job->state = JOB_SPAWNED;
730+
731+ TEST_EQ (job_next_state (job), JOB_POST_START_SETUP);
732+
733+ /* Check that the next state if we're starting a spawned job is
734 * post-start.
735 */
736 TEST_FEATURE ("with spawned job and a goal of start");
737 job->goal = JOB_START;
738- job->state = JOB_SPAWNED;
739+ job->state = JOB_POST_START_SETUP;
740
741 TEST_EQ (job_next_state (job), JOB_POST_START);
742
743@@ -4098,7 +4125,7 @@
744
745
746 /* Check that the next state if we're stopping a running job is
747- * pre-stop. This is the "normal" stop process, as called from the
748+ * pre-stop setup. This is the "normal" stop process, as called from the
749 * goal change event.
750 */
751 TEST_FEATURE ("with running job and a goal of stop");
752@@ -4106,6 +4133,17 @@
753 job->state = JOB_RUNNING;
754 job->pid[PROCESS_MAIN] = 1;
755
756+ TEST_EQ (job_next_state (job), JOB_PRE_STOP_SETUP);
757+
758+ /* Check that the next state if we're stopping a running job is
759+ * pre-stop.
760+ */
761+ TEST_FEATURE ("with running job and a goal of stop");
762+ job->goal = JOB_STOP;
763+ job->state = JOB_PRE_STOP_SETUP;
764+ job->pid[PROCESS_MAIN] = 1;
765+ job->pid[PROCESS_PRE_STOP] = 2;
766+
767 TEST_EQ (job_next_state (job), JOB_PRE_STOP);
768
769
770@@ -4193,7 +4231,7 @@
771 job->goal = JOB_START;
772 job->state = JOB_KILLED;
773
774- TEST_EQ (job_next_state (job), JOB_POST_STOP);
775+ TEST_EQ (job_next_state (job), JOB_POST_STOP_SETUP);
776
777
778 /* Check that the next state if we're stopping a killed job is
779@@ -4203,7 +4241,7 @@
780 job->goal = JOB_STOP;
781 job->state = JOB_KILLED;
782
783- TEST_EQ (job_next_state (job), JOB_POST_STOP);
784+ TEST_EQ (job_next_state (job), JOB_POST_STOP_SETUP);
785
786
787 /* Check that the next state if we're starting a post-stop job is
788
789=== modified file 'scripts/Makefile.am'
790--- scripts/Makefile.am 2013-11-14 11:42:05 +0000
791+++ scripts/Makefile.am 2014-04-08 20:51:56 +0000
792@@ -12,24 +12,24 @@
793 upstart-monitor.py
794
795 noinst_SCRIPTS = \
796- pyupstart.py
797+ pyupstart.py \
798+ pyupstartvars.py
799
800 CLEANFILES = \
801- pyupstart.py
802+ pyupstartvars.py pyupstartvars.py.tmp
803
804 EXTRA_DIST = \
805 $(install_scripts) \
806- pyupstart.py.in \
807+ pyupstart.py \
808 tests/__init__.py \
809 tests/test_pyupstart_session_init.py \
810 tests/test_pyupstart_system_init.py
811
812-pyupstart.py: pyupstart.py.in Makefile
813- sed -e 's|[@]built_init_binary[@]|$(UPSTART_BINARY)|g' \
814- -e 's|[@]built_initctl_binary[@]|$(INITCTL_BINARY)|g' \
815- -e 's|[@]built_file_bridge_binary[@]|$(FILE_BRIDGE_BINARY)|g' \
816- $< > $@
817- chmod +x $@
818+pyupstartvars.py: Makefile
819+ echo "BUILT_UPSTART = '$(UPSTART_BINARY)'" > pyupstartvars.py.tmp
820+ echo "BUILT_INITCTL = '$(INITCTL_BINARY)'" >> pyupstartvars.py.tmp
821+ echo "BUILT_FILE_BRIDGE = '$(FILE_BRIDGE_BINARY)'" >> pyupstartvars.py.tmp
822+ mv pyupstartvars.py.tmp pyupstartvars.py
823
824 dist_man_MANS = \
825 man/initctl2dot.8 \
826
827=== renamed file 'scripts/pyupstart.py.in' => 'scripts/pyupstart.py'
828--- scripts/pyupstart.py.in 2014-03-05 10:41:18 +0000
829+++ scripts/pyupstart.py 2014-04-08 20:51:56 +0000
830@@ -20,6 +20,8 @@
831 import pyinotify
832 import subprocess
833 import shutil
834+import sys
835+import unittest
836 import dbus
837 import dbus.service
838 import dbus.mainloop.glib
839@@ -28,6 +30,11 @@
840 from datetime import datetime, timedelta
841 from gi.repository import GLib
842
843+try:
844+ from pyupstartvars import *
845+except:
846+ pass
847+
848 VERSION = '0.1'
849 NAME = 'TestUpstart'
850
851@@ -36,10 +43,6 @@
852 SYSTEM_INITCTL = '/sbin/initctl'
853 SYSTEM_FILE_BRIDGE = '/sbin/upstart-file-bridge'
854
855-BUILT_UPSTART = '@built_init_binary@'
856-BUILT_INITCTL = '@built_initctl_binary@'
857-BUILT_FILE_BRIDGE = '@built_file_bridge_binary@'
858-
859 UPSTART_SESSION_ENV = 'UPSTART_SESSION'
860 USE_SYSTEM_BINARIES_ENV = 'UPSTART_TEST_USE_SYSTEM_BINARIES'
861
862@@ -64,6 +67,10 @@
863 OBJECT_PATH = '/com/ubuntu/Upstart'
864 FREEDESKTOP_PROPERTIES = 'org.freedesktop.DBus.Properties'
865
866+CGM_SOCKET = 'unix:path=/sys/fs/cgroup/cgmanager/sock'
867+CGM_INTERFACE_NAME = 'org.linuxcontainers.cgmanager0_0'
868+CGM_OBJECT_PATH = '/org/linuxcontainers/cgmanager'
869+
870 # Maximum number of seconds to wait for Upstart to detect a new job
871 # has been created
872 JOB_WAIT_SECS = 5
873@@ -83,6 +90,7 @@
874
875 #---------------------------------------------------------------------
876
877+
878 def get_init():
879 """
880 Return full path to an appropriate init daemon binary.
881@@ -95,6 +103,7 @@
882 assert (os.path.exists(binary))
883 return binary
884
885+
886 def get_initctl():
887 """
888 Return full path to an appropriate initctl binary.
889@@ -107,6 +116,7 @@
890 assert (os.path.exists(binary))
891 return binary
892
893+
894 def get_file_bridge():
895 """
896 Return full path to an appropriate upstart-file-bridge binary.
897@@ -119,6 +129,7 @@
898 assert (os.path.exists(binary))
899 return binary
900
901+
902 def dbus_encode(str):
903 """
904 Simulate nih_dbus_path() which Upstart uses to convert
905@@ -195,6 +206,13 @@
906 pass
907
908
909+class CGMException(Exception):
910+ """
911+ An Upstart Exception.
912+ """
913+ pass
914+
915+
916 class Upstart:
917 """
918 Upstart Class.
919@@ -972,6 +990,7 @@
920 self.stop()
921 self.logfile.destroy()
922
923+
924 class SystemInit(Upstart):
925
926 def __init__(self):
927@@ -991,6 +1010,59 @@
928 os.system('telinit u')
929
930
931+class CGManager():
932+
933+ def __init__(self, socket=CGM_SOCKET):
934+ self.socket = socket
935+ self.connection = None
936+ self.remote_object = None
937+ self.proxy = None
938+ self.connect()
939+ with open('/proc/cgroups') as f:
940+ self.all_cgroups = [l.split('\t')[0] for l in
941+ f.readlines() if not l.startswith('#')]
942+
943+ def connect(self, force=False):
944+ """
945+ Connect to CGManager.
946+
947+ @force: if True, connect regardless of whether already
948+ connected.
949+
950+ Notes:
951+ - Raises an CGMException() if already connected.
952+ """
953+ if self.connection and not force:
954+ raise CGMException('Already connected')
955+
956+ # Create appropriate D-Bus connection
957+ self.connection = dbus.connection.Connection(self.socket)
958+ self.remote_object = self.connection.get_object(
959+ object_path=CGM_OBJECT_PATH)
960+ self.proxy = dbus.Interface(self.remote_object, CGM_INTERFACE_NAME)
961+ self.Ping(0)
962+
963+ def api_version(self):
964+ """
965+ Determine api-version of running CGManager.
966+
967+ Returns: API Version as a string.
968+
969+ """
970+ properties = dbus.Interface(self.remote_object, FREEDESKTOP_PROPERTIES)
971+ return int(properties.Get(CGM_INTERFACE_NAME, 'api_version'))
972+
973+ def setup_sandbox(self, sandbox, pid):
974+ for controller in self.all_cgroups:
975+ if sandbox:
976+ self.Create(controller, sandbox)
977+ self.RemoveOnEmpty(controller, sandbox)
978+ self.MovePid(controller, sandbox, pid)
979+
980+ def __getattr__(self, name):
981+ return getattr(self.proxy, name)
982+
983+
984 class SessionInit(Upstart):
985 """
986 Create a new Upstart Session or join an existing one.
987@@ -1164,3 +1236,29 @@
988
989 self.logger.debug("Restarting Session Init")
990 self.proxy.Restart()
991+
992+def main():
993+ kwargs = {}
994+ format = \
995+ '%(asctime)s:' \
996+ '%(filename)s:' \
997+ '%(name)s:' \
998+ '%(funcName)s:' \
999+ '%(levelname)s:' \
1000+ '%(message)s'
1001+
1002+ kwargs['format'] = format
1003+
1004+ # We want to see what's happening
1005+ kwargs['level'] = logging.DEBUG
1006+
1007+ logging.basicConfig(**kwargs)
1008+
1009+ unittest.main(
1010+ testRunner=unittest.TextTestRunner(
1011+ stream=sys.stdout,
1012+ verbosity=2
1013+ )
1014+ )
1015+
1016+ sys.exit(0)
1017
1018=== added file 'scripts/tests/test_pyupstart_cgmanager.py'
1019--- scripts/tests/test_pyupstart_cgmanager.py 1970-01-01 00:00:00 +0000
1020+++ scripts/tests/test_pyupstart_cgmanager.py 2014-04-08 20:51:56 +0000
1021@@ -0,0 +1,63 @@
1022+#!/usr/bin/python3
1023+# -*- coding: utf-8 -*-
1024+#---------------------------------------------------------------------
1025+# Copyright © 2014 Canonical Ltd.
1026+#
1027+# Author: Dimitri John Ledkov <xnox@ubuntu.com>
1028+#
1029+# This program is free software; you can redistribute it and/or modify
1030+# it under the terms of the GNU General Public License version 2, as
1031+# published by the Free Software Foundation.
1032+#
1033+# This program is distributed in the hope that it will be useful,
1034+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1035+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1036+# GNU General Public License for more details.
1037+#
1038+# You should have received a copy of the GNU General Public License along
1039+# with this program; if not, write to the Free Software Foundation, Inc.,
1040+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1041+#---------------------------------------------------------------------
1042+
1043+#---------------------------------------------------------------------
1044+# Description: unit-tests for the CGManager() object
1045+#
1046+#---------------------------------------------------------------------
1047+
1048+import os
1049+import sys
1050+import tempfile
1051+import unittest
1052+
1053+base_dir = os.path.abspath(os.path.dirname(__file__))
1054+module_dir = os.path.normpath(os.path.realpath(base_dir + os.sep + '..'))
1055+
1056+# top-level unpacked source directory
1057+top_srcdir = os.path.normpath(os.path.realpath(module_dir + os.sep + '..'))
1058+
1059+# Tell Python where the uninstalled module lives in the source tree
1060+sys.path.append(module_dir)
1061+from pyupstart import *
1062+
1063+class TestCGManager(unittest.TestCase):
1064+ def setUp(self):
1065+ self.cg = CGManager()
1066+ self.tempfile = tempfile.NamedTemporaryFile(prefix='TestCGManager')
1067+ self.tempname = os.path.split(self.tempfile.name)[-1]
1068+
1069+ def test_init(self):
1070+ self.assertRaises(CGMException, self.cg.connect, ())
1071+
1072+ def test_api_version(self):
1073+ self.assertEqual(self.cg.api_version(), 2)
1074+
1075+ def test_setup_sandbox(self):
1076+ pid = os.getpid()
1077+ self.cg.setup_sandbox(self.tempname, pid)
1078+ with open('/proc/self/cgroup') as f:
1079+ missing = [l for l in f.readlines() if self.tempname not in l]
1080+ self.assertEqual(len(missing), 1)
1081+ self.assertTrue("name=systemd" in missing[0])
1082+
1083+if __name__ == '__main__':
1084+ main()
1085
1086=== modified file 'scripts/tests/test_pyupstart_session_init.py'
1087--- scripts/tests/test_pyupstart_session_init.py 2014-03-05 10:41:18 +0000
1088+++ scripts/tests/test_pyupstart_session_init.py 2014-04-08 20:51:56 +0000
1089@@ -539,31 +539,5 @@
1090 self.assertEqual(path, full_job_path)
1091 self.stop_session_init()
1092
1093-def main():
1094- kwargs = {}
1095- format = \
1096- '%(asctime)s:' \
1097- '%(filename)s:' \
1098- '%(name)s:' \
1099- '%(funcName)s:' \
1100- '%(levelname)s:' \
1101- '%(message)s'
1102-
1103- kwargs['format'] = format
1104-
1105- # We want to see what's happening
1106- kwargs['level'] = logging.DEBUG
1107-
1108- logging.basicConfig(**kwargs)
1109-
1110- unittest.main(
1111- testRunner=unittest.TextTestRunner(
1112- stream=sys.stdout,
1113- verbosity=2
1114- )
1115- )
1116-
1117- sys.exit(0)
1118-
1119 if __name__ == '__main__':
1120 main()
1121
1122=== added file 'scripts/tests/test_pyupstart_system_cgroups.py'
1123--- scripts/tests/test_pyupstart_system_cgroups.py 1970-01-01 00:00:00 +0000
1124+++ scripts/tests/test_pyupstart_system_cgroups.py 2014-04-08 20:51:56 +0000
1125@@ -0,0 +1,73 @@
1126+#!/usr/bin/python3
1127+# -*- coding: utf-8 -*-
1128+#---------------------------------------------------------------------
1129+# Copyright © 2014 Canonical Ltd.
1130+#
1131+# Author: Dimitri John Ledkov <xnox@ubuntu.com>
1132+#
1133+# This program is free software; you can redistribute it and/or modify
1134+# it under the terms of the GNU General Public License version 2, as
1135+# published by the Free Software Foundation.
1136+#
1137+# This program is distributed in the hope that it will be useful,
1138+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1139+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1140+# GNU General Public License for more details.
1141+#
1142+# You should have received a copy of the GNU General Public License along
1143+# with this program; if not, write to the Free Software Foundation, Inc.,
1144+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1145+#---------------------------------------------------------------------
1146+
1147+#---------------------------------------------------------------------
1148+# Description: unit-tests for the CGManager() object
1149+#
1150+#---------------------------------------------------------------------
1151+
1152+import os
1153+import sys
1154+import tempfile
1155+import unittest
1156+
1157+base_dir = os.path.abspath(os.path.dirname(__file__))
1158+module_dir = os.path.normpath(os.path.realpath(base_dir + os.sep + '..'))
1159+
1160+# top-level unpacked source directory
1161+top_srcdir = os.path.normpath(os.path.realpath(module_dir + os.sep + '..'))
1162+
1163+# Tell Python where the uninstalled module lives in the source tree
1164+sys.path.append(module_dir)
1165+from pyupstart import *
1166+from tests.test_pyupstart_system_init import TestSystemUpstart
1167+
1168+class TestSystemCGManager(TestSystemUpstart):
1169+ def setUp(self):
1170+ self.cg = CGManager()
1171+ self.tempfile = tempfile.NamedTemporaryFile(prefix='TestSystemCGManager')
1172+ self.tempname = os.path.split(self.tempfile.name)[-1]
1173+ self.cg.setup_sandbox(self.tempname, 1)
1174+ self.sample_job = [ "cgroup {} {}".format(cgroup, self.tempname)
1175+ for cgroup in self.cg.all_cgroups ]
1176+ self.sample_job.append('exec upstart-udev-bridge')
1177+ super().setUp()
1178+
1179+ def test_main(self):
1180+ job = self.upstart.job_create('main', self.sample_job)
1181+ job.start(wait=True)
1182+ self._assert_all_match(job.pids()['main'])
1183+
1184+ def test_pre_start(self):
1185+ self.sample_job.append('pre-start exec cat /proc/self/cgroup')
1186+ job = self.upstart.job_create('pre-start', self.sample_job)
1187+ job.start()
1188+ print(job.logfile_name())
1189+ # Kaboom!
1190+
1191+ def _assert_all_match(self, pid):
1192+ for c in self.cg.all_cgroups:
1193+ self.assertEqual(
1194+ self.cg.GetPidCgroup(c, pid),
1195+ self.tempname)
1196+
1197+if __name__ == '__main__':
1198+ main()
1199
1200=== modified file 'scripts/tests/test_pyupstart_system_init.py'
1201--- scripts/tests/test_pyupstart_system_init.py 2014-03-10 13:43:50 +0000
1202+++ scripts/tests/test_pyupstart_system_init.py 2014-04-08 20:51:56 +0000
1203@@ -167,31 +167,6 @@
1204 self.upstart.polling_connect(force=True)
1205 self.assertTrue(self.upstart.version())
1206
1207-def main():
1208- kwargs = {}
1209- format = \
1210- '%(asctime)s:' \
1211- '%(filename)s:' \
1212- '%(name)s:' \
1213- '%(funcName)s:' \
1214- '%(levelname)s:' \
1215- '%(message)s'
1216-
1217- kwargs['format'] = format
1218-
1219- # We want to see what's happening
1220- kwargs['level'] = logging.DEBUG
1221-
1222- logging.basicConfig(**kwargs)
1223-
1224- unittest.main(
1225- testRunner=unittest.TextTestRunner(
1226- stream=sys.stdout,
1227- verbosity=2
1228- )
1229- )
1230-
1231- sys.exit(0)
1232
1233 if __name__ == '__main__':
1234 main()

Subscribers

People subscribed via source and target branches