From 676769f786dac746dbe1d187cf03b701f918850b Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sun, 5 Sep 2010 05:56:53 +0100 Subject: [PATCH 1/3] Bug #630640: Duplicated power state constants Remove power state constants that have ended up duplicated following a bad merge. They were moved from nova.compute.node.Instance into nova.compute.power_state at the same time that Instance was moved into nova.compute.service. We've ended up with these constants in both places. Remove the ones from service, in favour of the ones in power_state. --- nova/tests/cloud_unittest.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nova/tests/cloud_unittest.py b/nova/tests/cloud_unittest.py index 900ff5a9..19aa23b9 100644 --- a/nova/tests/cloud_unittest.py +++ b/nova/tests/cloud_unittest.py @@ -28,6 +28,7 @@ from nova import flags from nova import rpc from nova import test from nova.auth import manager +from nova.compute import power_state from nova.compute import service from nova.endpoint import api from nova.endpoint import cloud @@ -95,7 +96,7 @@ class CloudTestCase(test.BaseTestCase): rv = yield defer.succeed(time.sleep(1)) info = self.cloud._get_instance(instance['instance_id']) logging.debug(info['state']) - if info['state'] == node.Instance.RUNNING: + if info['state'] == power_state.RUNNING: break self.assert_(rv) From d039d7a30bd6ac90c566f1890b288a7010ce79f8 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 13 Sep 2010 09:03:14 +0200 Subject: [PATCH 2/3] Move vol.destroy() call out of the _check method in test_multiple_volume_race_condition test and into a callback of the DeferredList. This should fix the intermittent failure of that test. I /think/ test_too_many_volumes's failure was caused by test_multiple_volume_race_condition failure, since I have not been able to reproduce its failure after fixing this one. --- nova/tests/volume_unittest.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/nova/tests/volume_unittest.py b/nova/tests/volume_unittest.py index 2a07afe6..540b7158 100644 --- a/nova/tests/volume_unittest.py +++ b/nova/tests/volume_unittest.py @@ -128,7 +128,6 @@ class VolumeTestCase(test.TrialTestCase): volume_service.get_volume, volume_id) - @defer.inlineCallbacks def test_multiple_volume_race_condition(self): vol_size = "5" user_id = "fake" @@ -137,17 +136,28 @@ class VolumeTestCase(test.TrialTestCase): def _check(volume_id): vol = volume_service.get_volume(volume_id) shelf_blade = '%s.%s' % (vol['shelf_id'], vol['blade_id']) - self.assert_(shelf_blade not in shelf_blades) + self.assertTrue(shelf_blade not in shelf_blades, + "Same shelf/blade tuple came back twice") shelf_blades.append(shelf_blade) logging.debug("got %s" % shelf_blade) - vol.destroy() + return vol deferreds = [] for i in range(5): d = self.volume.create_volume(vol_size, user_id, project_id) d.addCallback(_check) d.addErrback(self.fail) deferreds.append(d) - yield defer.DeferredList(deferreds) + def destroy_volumes(retvals): + overall_succes = True + for success, volume in retvals: + if not success: + overall_succes = False + else: + volume.destroy() + self.assertTrue(overall_succes) + d = defer.DeferredList(deferreds) + d.addCallback(destroy_volumes) + return d def test_multi_node(self): # TODO(termie): Figure out how to test with two nodes, From 48bacdd68accf7f4dfeca413c6ecc9fb499efd5b Mon Sep 17 00:00:00 2001 From: Jesse Andrews Date: Mon, 13 Sep 2010 00:06:32 -0700 Subject: [PATCH 3/3] add a shell to nova-manage, which respects flags (taken from django) --- bin/nova-manage | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/bin/nova-manage b/bin/nova-manage index d2fd49d8..6e526676 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -17,6 +17,37 @@ # License for the specific language governing permissions and limitations # under the License. +# Interactive shell based on Django: +# +# Copyright (c) 2005, the Lawrence Journal-World +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of Django nor the names of its contributors may be used +# to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + """ CLI interface for nova management. Connects to the running ADMIN api in the api daemon. @@ -103,6 +134,29 @@ class VpnCommands(object): self.pipe.launch_vpn_instance(project_id) +class ShellCommands(object): + def run(self): + "Runs a Python interactive interpreter. Tries to use IPython, if it's available." + try: + import IPython + # Explicitly pass an empty list as arguments, because otherwise IPython + # would use sys.argv from this script. + shell = IPython.Shell.IPShell(argv=[]) + shell.mainloop() + except ImportError: + import code + try: # Try activating rlcompleter, because it's handy. + import readline + except ImportError: + pass + else: + # We don't have to wrap the following import in a 'try', because + # we already know 'readline' was imported successfully. + import rlcompleter + readline.parse_and_bind("tab:complete") + code.interact() + + class RoleCommands(object): """Class for managing roles.""" @@ -225,6 +279,7 @@ CATEGORIES = [ ('user', UserCommands), ('project', ProjectCommands), ('role', RoleCommands), + ('shell', ShellCommands), ('vpn', VpnCommands), ]