diff --git a/circle/vm/operations.py b/circle/vm/operations.py index 95640b3..0550b0f 100644 --- a/circle/vm/operations.py +++ b/circle/vm/operations.py @@ -157,6 +157,11 @@ class DeployOperation(InstanceOperation): name = _("deploy") description = _("Deploy new virtual machine with network.") + def check_precond(self): + super(DeployOperation, self).check_precond() + if self.instance.status in ['RUNNING', 'SUSPENDED']: + raise self.instance.WrongStateError(self.instance) + def on_commit(self, activity): activity.resultant_state = 'RUNNING' @@ -238,6 +243,11 @@ class MigrateOperation(InstanceOperation): with activity.sub_activity('rollback_net'): self.instance.deploy_net() + def check_precond(self): + super(MigrateOperation, self).check_precond() + if self.instance.status not in ['RUNNING']: + raise self.instance.WrongStateError(self.instance) + def check_auth(self, user): if not user.is_superuser: raise PermissionDenied() @@ -279,6 +289,11 @@ class RebootOperation(InstanceOperation): name = _("reboot") description = _("Reboot virtual machine with Ctrl+Alt+Del signal.") + def check_precond(self): + super(RebootOperation, self).check_precond() + if self.instance.status not in ['RUNNING']: + raise self.instance.WrongStateError(self.instance) + def _operation(self, timeout=5): self.instance.reboot_vm(timeout=timeout) @@ -329,6 +344,11 @@ class ResetOperation(InstanceOperation): name = _("reset") description = _("Reset virtual machine (reset button).") + def check_precond(self): + super(ResetOperation, self).check_precond() + if self.instance.status not in ['RUNNING']: + raise self.instance.WrongStateError(self.instance) + def _operation(self, timeout=5): self.instance.reset_vm(timeout=timeout) @@ -362,6 +382,11 @@ class SaveAsTemplateOperation(InstanceOperation): for disk in self.disks: disk.destroy() + def check_precond(self): + super(SaveAsTemplateOperation, self).check_precond() + if self.instance.status not in ['RUNNING', 'PENDING', 'STOPPED']: + raise self.instance.WrongStateError(self.instance) + def _operation(self, activity, user, system, timeout=300, name=None, with_shutdown=True, task=None, **kwargs): if with_shutdown: @@ -456,6 +481,11 @@ class ShutOffOperation(InstanceOperation): name = _("shut off") description = _("Shut off VM (plug-out).") + def check_precond(self): + super(ShutOffOperation, self).check_precond() + if self.instance.status not in ['RUNNING']: + raise self.instance.WrongStateError(self.instance) + def on_commit(self, activity): activity.resultant_state = 'STOPPED' diff --git a/circle/vm/tests/test_models.py b/circle/vm/tests/test_models.py index 885add3..8487560 100644 --- a/circle/vm/tests/test_models.py +++ b/circle/vm/tests/test_models.py @@ -103,6 +103,7 @@ class InstanceTestCase(TestCase): inst = Mock(destroyed_at=None, spec=Instance) inst.interface_set.all.return_value = [] inst.node = MagicMock(spec=Node) + inst.status = 'RUNNING' migrate_op = MigrateOperation(inst) with patch('vm.models.instance.vm_tasks.migrate') as migr: act = MagicMock() @@ -118,6 +119,7 @@ class InstanceTestCase(TestCase): inst = MagicMock(destroyed_at=None, spec=Instance) inst.interface_set.all.return_value = [] inst.node = MagicMock(spec=Node) + inst.status = 'RUNNING' migrate_op = MigrateOperation(inst) with patch('vm.models.instance.vm_tasks.migrate') as migr: inst.select_node.side_effect = AssertionError @@ -133,6 +135,7 @@ class InstanceTestCase(TestCase): inst = Mock(destroyed_at=None, spec=Instance) inst.interface_set.all.return_value = [] inst.node = MagicMock(spec=Node) + inst.status = 'RUNNING' e = Exception('abc') setattr(e, 'libvirtError', '') inst.migrate_vm.side_effect = e