Merge "Show an error message on instance launch error"

This commit is contained in:
Jenkins
2013-10-08 04:28:25 +00:00
committed by Gerrit Code Review
3 changed files with 113 additions and 1 deletions

View File

@@ -71,7 +71,7 @@ class Server(base.APIResourceWrapper):
"""
_attrs = ['addresses', 'attrs', 'id', 'image', 'links',
'metadata', 'name', 'private_ip', 'public_ip', 'status', 'uuid',
'image_name', 'VirtualInterfaces', 'flavor', 'key_name',
'image_name', 'VirtualInterfaces', 'flavor', 'key_name', 'fault',
'tenant_id', 'user_id', 'OS-EXT-STS:power_state',
'OS-EXT-STS:task_state', 'OS-EXT-SRV-ATTR:instance_name',
'OS-EXT-SRV-ATTR:host', 'created']

View File

@@ -431,6 +431,29 @@ class SimpleDisassociateIP(tables.Action):
return shortcuts.redirect("horizon:project:instances:index")
def instance_fault_to_friendly_message(instance):
fault = getattr(instance, 'fault', {})
message = fault.get('message', _("Unknown"))
default_message = _("Please try again later [Error: %s].") % message
fault_map = {
'NoValidHost': _("There is not enough capacity for this "
"flavor in the selected availability zone. "
"Try again later or select a different availability "
"zone.")
}
return fault_map.get(message, default_message)
def get_instance_error(instance):
if instance.status.lower() != 'error':
return None
message = instance_fault_to_friendly_message(instance)
preamble = _('Failed to launch instance "%s"'
) % instance.name or instance.id
message = string_concat(preamble, ': ', message)
return message
class UpdateRow(tables.Row):
ajax = True
@@ -438,6 +461,9 @@ class UpdateRow(tables.Row):
instance = api.nova.server_get(request, instance_id)
instance.full_flavor = api.nova.flavor_get(request,
instance.flavor["id"])
error = get_instance_error(instance)
if error:
messages.error(request, error)
return instance

View File

@@ -18,6 +18,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import json
import uuid
from django.core.urlresolvers import reverse # noqa
@@ -2043,3 +2044,88 @@ class InstanceTests(test.TestCase):
password=password,
confirm_password=password)
self.assertRedirectsNoFollow(res, INDEX_URL)
class InstanceAjaxTests(test.TestCase):
@test.create_stubs({api.nova: ("server_get",
"flavor_get",
"extension_supported"),
api.neutron: ("is_extension_supported",)})
def test_row_update(self):
server = self.servers.first()
instance_id = server.id
flavor_id = server.flavor["id"]
flavors = self.flavors.list()
full_flavors = SortedDict([(f.id, f) for f in flavors])
api.nova.extension_supported('AdminActions', IsA(http.HttpRequest))\
.MultipleTimes().AndReturn(True)
api.neutron.is_extension_supported(IsA(http.HttpRequest),
'security-group')\
.MultipleTimes().AndReturn(True)
api.nova.server_get(IsA(http.HttpRequest), instance_id)\
.AndReturn(server)
api.nova.flavor_get(IsA(http.HttpRequest), flavor_id)\
.AndReturn(full_flavors[flavor_id])
self.mox.ReplayAll()
params = {'action': 'row_update',
'table': 'instances',
'obj_id': instance_id,
}
res = self.client.get('?'.join((INDEX_URL, urlencode(params))),
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
self.assertContains(res, server.name)
@test.create_stubs({api.nova: ("server_get",
"flavor_get",
"extension_supported"),
api.neutron: ("is_extension_supported",)})
def test_row_update_instance_error(self):
server = self.servers.first()
instance_id = server.id
flavor_id = server.flavor["id"]
flavors = self.flavors.list()
full_flavors = SortedDict([(f.id, f) for f in flavors])
server.status = 'ERROR'
server.fault = {"message": "NoValidHost",
"code": 500,
"details": "No valid host was found. \n "
"File \"/mnt/stack/nova/nova/"
"scheduler/filter_scheduler.py\", "
"line 105, in schedule_run_instance\n "
"raise exception.NoValidHost"
"(reason=\"\")\n",
"created": "2013-10-07T00:08:32Z"}
api.nova.extension_supported('AdminActions', IsA(http.HttpRequest))\
.MultipleTimes().AndReturn(True)
api.neutron.is_extension_supported(IsA(http.HttpRequest),
'security-group')\
.MultipleTimes().AndReturn(True)
api.nova.server_get(IsA(http.HttpRequest), instance_id)\
.AndReturn(server)
api.nova.flavor_get(IsA(http.HttpRequest), flavor_id)\
.AndReturn(full_flavors[flavor_id])
self.mox.ReplayAll()
params = {'action': 'row_update',
'table': 'instances',
'obj_id': instance_id,
}
res = self.client.get('?'.join((INDEX_URL, urlencode(params))),
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
self.assertContains(res, server.name)
self.assertTrue(res.has_header('X-Horizon-Messages'))
messages = json.loads(res['X-Horizon-Messages'])
self.assertEqual(len(messages), 1)
# (Pdb) messages
# [[u'error', u'Failed to launch instance "server_1": \
# There is not enough capacity for this flavor in the \
# selected availability zone. Try again later or select \
# a different availability zone.', u'']]
self.assertEqual(messages[0][0], 'error')
self.assertTrue(messages[0][1].startswith('Failed'))