Merge lp:~soren/nova/lp733609 into lp:~hudson-openstack/nova/trunk

Proposed by Soren Hansen
Status: Merged
Approved by: Rick Harris
Approved revision: 797
Merged at revision: 822
Proposed branch: lp:~soren/nova/lp733609
Merge into: lp:~hudson-openstack/nova/trunk
Diff against target: 143 lines (+93/-10)
2 files modified
nova/tests/test_utils.py (+78/-0)
nova/utils.py (+15/-10)
To merge this branch: bzr merge lp:~soren/nova/lp733609
Reviewer Review Type Date Requested Status
Rick Harris (community) Approve
Paul Voccio (community) Approve
Review via email: mp+53321@code.launchpad.net

Commit message

Make utils.execute not overwrite std{in,out,err} args to Popen on retries.
Make utils.execute reject unknown kwargs.

Add a couple of unit tests for utils.execute.

To post a comment you must log in.
Revision history for this message
Paul Voccio (pvo) wrote :

lgtm

review: Approve
Revision history for this message
Rick Harris (rconradharris) wrote :

Patch looks really good.

Received a few pep8 nits from the test-suite: http://paste.openstack.org/show/921/

review: Needs Fixing
Revision history for this message
Soren Hansen (soren) wrote :

> Patch looks really good.
>
> Received a few pep8 nits from the test-suite:
> http://paste.openstack.org/show/921/

*sigh* Fixed. I keep forgetting to run pep8 manually (because I have that test case that fails due to non-ascii stuff in the help text, so run_tests.sh skips pep8). I've given myself a good shouting at. Apologies. :(

lp:~soren/nova/lp733609 updated
797. By Soren Hansen

pep8

Revision history for this message
Rick Harris (rconradharris) wrote :

lgtm, thanks for the fixes.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'nova/tests/test_utils.py'
2--- nova/tests/test_utils.py 2011-02-23 22:07:08 +0000
3+++ nova/tests/test_utils.py 2011-03-17 20:46:29 +0000
4@@ -14,11 +14,89 @@
5 # License for the specific language governing permissions and limitations
6 # under the License.
7
8+import os
9+import tempfile
10+
11 from nova import test
12 from nova import utils
13 from nova import exception
14
15
16+class ExecuteTestCase(test.TestCase):
17+ def test_retry_on_failure(self):
18+ fd, tmpfilename = tempfile.mkstemp()
19+ _, tmpfilename2 = tempfile.mkstemp()
20+ try:
21+ fp = os.fdopen(fd, 'w+')
22+ fp.write('''#!/bin/sh
23+# If stdin fails to get passed during one of the runs, make a note.
24+if ! grep -q foo
25+then
26+ echo 'failure' > "$1"
27+fi
28+# If stdin has failed to get passed during this or a previous run, exit early.
29+if grep failure "$1"
30+then
31+ exit 1
32+fi
33+runs="$(cat $1)"
34+if [ -z "$runs" ]
35+then
36+ runs=0
37+fi
38+runs=$(($runs + 1))
39+echo $runs > "$1"
40+exit 1
41+''')
42+ fp.close()
43+ os.chmod(tmpfilename, 0755)
44+ self.assertRaises(exception.ProcessExecutionError,
45+ utils.execute,
46+ tmpfilename, tmpfilename2, attempts=10,
47+ process_input='foo',
48+ delay_on_retry=False)
49+ fp = open(tmpfilename2, 'r+')
50+ runs = fp.read()
51+ fp.close()
52+ self.assertNotEquals(runs.strip(), 'failure', 'stdin did not '
53+ 'always get passed '
54+ 'correctly')
55+ runs = int(runs.strip())
56+ self.assertEquals(runs, 10,
57+ 'Ran %d times instead of 10.' % (runs,))
58+ finally:
59+ os.unlink(tmpfilename)
60+ os.unlink(tmpfilename2)
61+
62+ def test_unknown_kwargs_raises_error(self):
63+ self.assertRaises(exception.Error,
64+ utils.execute,
65+ '/bin/true', this_is_not_a_valid_kwarg=True)
66+
67+ def test_no_retry_on_success(self):
68+ fd, tmpfilename = tempfile.mkstemp()
69+ _, tmpfilename2 = tempfile.mkstemp()
70+ try:
71+ fp = os.fdopen(fd, 'w+')
72+ fp.write('''#!/bin/sh
73+# If we've already run, bail out.
74+grep -q foo "$1" && exit 1
75+# Mark that we've run before.
76+echo foo > "$1"
77+# Check that stdin gets passed correctly.
78+grep foo
79+''')
80+ fp.close()
81+ os.chmod(tmpfilename, 0755)
82+ utils.execute(tmpfilename,
83+ tmpfilename2,
84+ process_input='foo',
85+ attempts=2)
86+ finally:
87+ os.unlink(tmpfilename)
88+ os.unlink(tmpfilename2)
89+
90+
91 class GetFromPathTestCase(test.TestCase):
92 def test_tolerates_nones(self):
93 f = utils.get_from_path
94
95=== modified file 'nova/utils.py'
96--- nova/utils.py 2011-03-16 20:36:22 +0000
97+++ nova/utils.py 2011-03-17 20:46:29 +0000
98@@ -133,13 +133,14 @@
99
100
101 def execute(*cmd, **kwargs):
102- process_input = kwargs.get('process_input', None)
103- addl_env = kwargs.get('addl_env', None)
104- check_exit_code = kwargs.get('check_exit_code', 0)
105- stdin = kwargs.get('stdin', subprocess.PIPE)
106- stdout = kwargs.get('stdout', subprocess.PIPE)
107- stderr = kwargs.get('stderr', subprocess.PIPE)
108- attempts = kwargs.get('attempts', 1)
109+ process_input = kwargs.pop('process_input', None)
110+ addl_env = kwargs.pop('addl_env', None)
111+ check_exit_code = kwargs.pop('check_exit_code', 0)
112+ delay_on_retry = kwargs.pop('delay_on_retry', True)
113+ attempts = kwargs.pop('attempts', 1)
114+ if len(kwargs):
115+ raise exception.Error(_('Got unknown keyword args '
116+ 'to utils.execute: %r') % kwargs)
117 cmd = map(str, cmd)
118
119 while attempts > 0:
120@@ -149,8 +150,11 @@
121 env = os.environ.copy()
122 if addl_env:
123 env.update(addl_env)
124- obj = subprocess.Popen(cmd, stdin=stdin,
125- stdout=stdout, stderr=stderr, env=env)
126+ obj = subprocess.Popen(cmd,
127+ stdin=subprocess.PIPE,
128+ stdout=subprocess.PIPE,
129+ stderr=subprocess.PIPE,
130+ env=env)
131 result = None
132 if process_input != None:
133 result = obj.communicate(process_input)
134@@ -176,7 +180,8 @@
135 raise
136 else:
137 LOG.debug(_("%r failed. Retrying."), cmd)
138- greenthread.sleep(random.randint(20, 200) / 100.0)
139+ if delay_on_retry:
140+ greenthread.sleep(random.randint(20, 200) / 100.0)
141
142
143 def ssh_execute(ssh, cmd, process_input=None,