Commit f69d7306 by Bach Dániel

Merge branch 'fix-http500' into 'master'

Fix http500

🚧 tests

See merge request !223
parents 83f7bd1e b841385c
...@@ -13,7 +13,7 @@ Choose a compute node to migrate {{obj}} to. ...@@ -13,7 +13,7 @@ Choose a compute node to migrate {{obj}} to.
{% block formfields %} {% block formfields %}
<ul id="vm-migrate-node-list" class="list-unstyled"> <ul id="vm-migrate-node-list" class="list-unstyled">
{% with current=object.node.pk selected=object.select_node.pk %} {% with current=object.node.pk %}
{% for n in nodes %} {% for n in nodes %}
<li class="panel panel-default"><div class="panel-body"> <li class="panel panel-default"><div class="panel-body">
<label for="migrate-to-{{n.pk}}"> <label for="migrate-to-{{n.pk}}">
...@@ -21,11 +21,11 @@ Choose a compute node to migrate {{obj}} to. ...@@ -21,11 +21,11 @@ Choose a compute node to migrate {{obj}} to.
<div class="label label-primary"><i class="fa {{n.get_status_icon}}"></i> <div class="label label-primary"><i class="fa {{n.get_status_icon}}"></i>
{{n.get_status_display}}</div> {{n.get_status_display}}</div>
{% if current == n.pk %}<div class="label label-info">{% trans "current" %}</div>{% endif %} {% if current == n.pk %}<div class="label label-info">{% trans "current" %}</div>{% endif %}
{% if selected == n.pk %}<div class="label label-success">{% trans "recommended" %}</div>{% endif %} {% if recommended == n.pk %}<div class="label label-success">{% trans "recommended" %}</div>{% endif %}
</label> </label>
<input id="migrate-to-{{n.pk}}" type="radio" name="node" value="{{ n.pk }}" style="float: right;" <input id="migrate-to-{{n.pk}}" type="radio" name="node" value="{{ n.pk }}" style="float: right;"
{% if current == n.pk %}disabled="disabled"{% endif %} {% if current == n.pk %}disabled="disabled"{% endif %}
{% if selected == n.pk %}checked="checked"{% endif %} /> {% if recommended == n.pk %}checked="checked"{% endif %} />
<span class="vm-migrate-node-property">{% trans "CPU load" %}: {{ n.cpu_usage }}</span> <span class="vm-migrate-node-property">{% trans "CPU load" %}: {{ n.cpu_usage }}</span>
<span class="vm-migrate-node-property">{% trans "RAM usage" %}: {{ n.byte_ram_usage|filesize }}/{{ n.ram_size|filesize }}</span> <span class="vm-migrate-node-property">{% trans "RAM usage" %}: {{ n.byte_ram_usage|filesize }}/{{ n.ram_size|filesize }}</span>
<div style="clear: both;"></div> <div style="clear: both;"></div>
......
...@@ -45,6 +45,7 @@ from common.models import ( ...@@ -45,6 +45,7 @@ from common.models import (
create_readable, HumanReadableException, fetch_human_exception, create_readable, HumanReadableException, fetch_human_exception,
) )
from firewall.models import Vlan, Host, Rule from firewall.models import Vlan, Host, Rule
from manager.scheduler import SchedulerError
from storage.models import Disk from storage.models import Disk
from vm.models import ( from vm.models import (
Instance, instance_activity, InstanceActivity, Node, Lease, Instance, instance_activity, InstanceActivity, Node, Lease,
...@@ -424,6 +425,15 @@ class VmMigrateView(VmOperationView): ...@@ -424,6 +425,15 @@ class VmMigrateView(VmOperationView):
ctx = super(VmMigrateView, self).get_context_data(**kwargs) ctx = super(VmMigrateView, self).get_context_data(**kwargs)
ctx['nodes'] = [n for n in Node.objects.filter(enabled=True) ctx['nodes'] = [n for n in Node.objects.filter(enabled=True)
if n.online] if n.online]
inst = self.get_object()
ctx["recommended"] = None
try:
if isinstance(inst, Instance):
ctx["recommended"] = inst.select_node().pk
except SchedulerError:
logger.exception("scheduler error:")
return ctx return ctx
def post(self, request, extra=None, *args, **kwargs): def post(self, request, extra=None, *args, **kwargs):
......
...@@ -920,6 +920,13 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin, ...@@ -920,6 +920,13 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
delete_dump.apply_async(args=[self.mem_dump['path']], delete_dump.apply_async(args=[self.mem_dump['path']],
queue=queue_name).get(timeout=timeout) queue=queue_name).get(timeout=timeout)
def reallocate_node(self, activity):
with activity.sub_activity(
'scheduling',
readable_name=ugettext_noop("schedule")) as sa:
sa.result = node = self.select_node()
return node
def allocate_node(self, activity): def allocate_node(self, activity):
if self.node is not None: if self.node is not None:
return None return None
......
...@@ -114,8 +114,8 @@ class Node(OperatedMixin, TimeStampedModel): ...@@ -114,8 +114,8 @@ class Node(OperatedMixin, TimeStampedModel):
def get_info(self): def get_info(self):
return self.remote_query(vm_tasks.get_info, return self.remote_query(vm_tasks.get_info,
priority='fast', priority='fast',
default={'core_num': '', default={'core_num': 0,
'ram_size': '0', 'ram_size': 0,
'architecture': ''}) 'architecture': ''})
info = property(get_info) info = property(get_info)
......
...@@ -398,7 +398,7 @@ class MigrateOperation(InstanceOperation): ...@@ -398,7 +398,7 @@ class MigrateOperation(InstanceOperation):
def _operation(self, activity, to_node=None, timeout=120): def _operation(self, activity, to_node=None, timeout=120):
if not to_node: if not to_node:
self.instance.allocate_node(activity) to_node = self.instance.reallocate_node(activity)
try: try:
with activity.sub_activity( with activity.sub_activity(
'migrate_vm', readable_name=create_readable( 'migrate_vm', readable_name=create_readable(
...@@ -418,6 +418,7 @@ class MigrateOperation(InstanceOperation): ...@@ -418,6 +418,7 @@ class MigrateOperation(InstanceOperation):
# Refresh node information # Refresh node information
self.instance.node = to_node self.instance.node = to_node
self.instance.save() self.instance.save()
# Estabilish network connection (vmdriver) # Estabilish network connection (vmdriver)
with activity.sub_activity( with activity.sub_activity(
'deploying_net', readable_name=ugettext_noop( 'deploying_net', readable_name=ugettext_noop(
......
...@@ -16,9 +16,10 @@ ...@@ -16,9 +16,10 @@
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>. # with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from django.test import TestCase from django.test import TestCase
from mock import MagicMock
from common.operations import operation_registry_name as op_reg_name from common.operations import operation_registry_name as op_reg_name
from vm.models import Instance, Node from vm.models import Instance, InstanceActivity, Node
from vm.operations import ( from vm.operations import (
DeployOperation, DestroyOperation, FlushOperation, MigrateOperation, DeployOperation, DestroyOperation, FlushOperation, MigrateOperation,
RebootOperation, ResetOperation, SaveAsTemplateOperation, RebootOperation, ResetOperation, SaveAsTemplateOperation,
...@@ -45,6 +46,22 @@ class MigrateOperationTestCase(TestCase): ...@@ -45,6 +46,22 @@ class MigrateOperationTestCase(TestCase):
def test_operation_registered(self): def test_operation_registered(self):
assert MigrateOperation.id in getattr(Instance, op_reg_name) assert MigrateOperation.id in getattr(Instance, op_reg_name)
def test_operation_wo_to_node_param(self):
class MigrateException(Exception):
pass
inst = MagicMock(spec=Instance)
act = MagicMock(spec=InstanceActivity)
inst.migrate_vm = MagicMock(side_effect=MigrateException())
inst.select_node = MagicMock(return_value='test')
inst.reallocate_node = (
lambda act: Instance.reallocate_node(inst, act))
self.assertRaises(
MigrateException, MigrateOperation(inst)._operation,
act, to_node=None)
assert inst.select_node.called
inst.migrate_vm.assert_called_once_with(to_node='test', timeout=120)
class RebootOperationTestCase(TestCase): class RebootOperationTestCase(TestCase):
def test_operation_registered(self): def test_operation_registered(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment