Commit 6636656e by Dudás Ádám

vm: refactor operations

parent ebfd1921
......@@ -2,6 +2,7 @@ from __future__ import absolute_import, unicode_literals
from datetime import timedelta
from importlib import import_module
from logging import getLogger
from string import ascii_lowercase
from warnings import warn
import django.conf
......@@ -726,94 +727,136 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
"""
return scheduler.select_node(self, Node.objects.all())
def _schedule_vm(self, act):
"""Schedule the virtual machine as part of a higher level activity.
:param act: Parent activity.
def deploy_disks(self):
"""Deploy all associated disks.
"""
# Find unused port for VNC
if self.vnc_port is None:
self.vnc_port = find_unused_vnc_port()
# Schedule
if self.node is None:
self.node = self.select_node()
self.save()
devnums = list(ascii_lowercase) # a-z
for disk in self.disks.all():
# assign device numbers
if disk.dev_num in devnums:
devnums.remove(disk.dev_num)
else:
disk.dev_num = devnums.pop(0)
disk.save()
# deploy disk
disk.deploy()
def _deploy_vm(self, act, timeout=15):
"""Deploy the virtual machine.
:param self: The virtual machine.
def destroy_disks(self):
"""Destroy all associated disks.
"""
for disk in self.disks.all():
disk.destroy()
:param act: Parent activity.
def deploy_net(self):
"""Deploy all associated network interfaces.
"""
queue_name = self.get_remote_queue_name('vm')
for net in self.interface_set.all():
net.deploy()
# Deploy VM on remote machine
with act.sub_activity('deploying_vm') as deploy_act:
deploy_act.result = vm_tasks.deploy.apply_async(
args=[self.get_vm_desc()],
queue=queue_name).get(timeout=timeout)
def destroy_net(self):
"""Destroy all associated network interfaces.
"""
for net in self.interface_set.all():
net.destroy()
# Estabilish network connection (vmdriver)
with act.sub_activity('deploying_net'):
for net in self.interface_set.all():
net.deploy()
def shutdown_net(self):
"""Shutdown all associated network interfaces.
"""
for net in self.interface_set.all():
net.shutdown()
# Resume vm
with act.sub_activity('booting'):
vm_tasks.resume.apply_async(args=[self.vm_name],
queue=queue_name).get(timeout=timeout)
def delete_vm(self, timeout=15):
queue_name = self.get_remote_queue_name('vm')
try:
return vm_tasks.destroy.apply_async(args=[self.vm_name],
queue=queue_name
).get(timeout=timeout)
except Exception as e:
if e.libvirtError and "Domain not found" in str(e):
logger.debug("Domain %s was not found at %s"
% (self.vm_name, queue_name))
else:
raise
def deploy_vm(self, timeout=15):
queue_name = self.get_remote_queue_name('vm')
return vm_tasks.deploy.apply_async(args=[self.get_vm_desc()],
queue=queue_name
).get(timeout=timeout)
self.renew(which='both', base_activity=act)
def migrate_vm(self, to_node, timeout=120):
queue_name = self.get_remote_queue_name('vm')
return vm_tasks.migrate.apply_async(args=[self.vm_name,
to_node.host.hostname],
queue=queue_name
).get(timeout=timeout)
def _destroy_vm(self, act, timeout=15):
"""Destroy the virtual machine and its associated networks.
def reboot_vm(self, timeout=5):
queue_name = self.get_remote_queue_name('vm')
return vm_tasks.reboot.apply_async(args=[self.vm_name],
queue=queue_name
).get(timeout=timeout)
:param self: The virtual machine.
def reset_vm(self, timeout=5):
queue_name = self.get_remote_queue_name('vm')
return vm_tasks.reset.apply_async(args=[self.vm_name],
queue=queue_name
).get(timeout=timeout)
:param act: Parent activity.
"""
# Destroy networks
with act.sub_activity('destroying_net'):
for net in self.interface_set.all():
net.destroy()
def resume_vm(self, timeout=15):
queue_name = self.get_remote_queue_name('vm')
return vm_tasks.resume.apply_async(args=[self.vm_name],
queue=queue_name
).get(timeout=timeout)
# Destroy virtual machine
with act.sub_activity('destroying_vm'):
queue_name = self.get_remote_queue_name('vm')
try:
vm_tasks.destroy.apply_async(args=[self.vm_name],
def shutdown_vm(self, timeout=120):
queue_name = self.get_remote_queue_name('vm')
logger.debug("RPC Shutdown at queue: %s, for vm: %s.", queue_name,
self.vm_name)
return vm_tasks.shutdown.apply_async(kwargs={'name': self.vm_name},
queue=queue_name
).get(timeout=timeout)
except Exception as e:
if e.libvirtError and "Domain not found" in str(e):
logger.debug("Domain %s was not found at %s"
% (self.vm_name, queue_name))
else:
raise
def _cleanup_after_destroy_vm(self, act, timeout=15):
"""Clean up the virtual machine's data after destroy.
def suspend_vm(self, timeout=60):
queue_name = self.get_remote_queue_name('vm')
return vm_tasks.sleep.apply_async(args=[self.vm_name,
self.mem_dump['path']],
queue=queue_name
).get(timeout=timeout)
:param self: The virtual machine.
def wake_up_vm(self, timeout=60):
queue_name = self.get_remote_queue_name('vm')
return vm_tasks.wake_up.apply_async(args=[self.vm_name,
self.mem_dump['path']],
queue=queue_name
).get(timeout=timeout)
def delete_mem_dump(self, timeout=15):
queue_name = self.mem_dump['datastore'].get_remote_queue_name(
'storage')
from storage.tasks.remote_tasks import delete_dump
delete_dump.apply_async(args=[self.mem_dump['path']],
queue=queue_name).get(timeout=timeout)
def allocate_node(self):
if self.node is None:
self.node = self.select_node()
self.save()
:param act: Parent activity.
"""
# Delete mem. dump if exists
try:
queue_name = self.mem_dump['datastore'].get_remote_queue_name(
'storage')
from storage.tasks.remote_tasks import delete_dump
delete_dump.apply_async(args=[self.mem_dump['path']],
queue=queue_name).get(timeout=timeout)
except:
pass
def yield_node(self):
if self.node is not None:
self.node = None
self.save()
# Clear node and VNC port association
self.node = None
self.vnc_port = None
def allocate_vnc_port(self):
if self.vnc_port is None:
self.vnc_port = find_unused_vnc_port()
self.save()
def yield_vnc_port(self):
if self.vnc_port is not None:
self.vnc_port = None
self.save()
def get_status_icon(self):
return {
......
from __future__ import absolute_import, unicode_literals
from logging import getLogger
from string import ascii_lowercase
from django.core.exceptions import PermissionDenied
from django.utils import timezone
......@@ -10,7 +9,6 @@ from celery.exceptions import TimeLimitExceeded
from common.operations import Operation, register_operation
from storage.models import Disk
from .tasks import vm_tasks
from .tasks.local_tasks import async_instance_operation, async_node_operation
from .models import (
Instance, InstanceActivity, InstanceTemplate, Node, NodeActivity,
......@@ -70,23 +68,28 @@ class DeployOperation(InstanceOperation):
def on_commit(self, activity):
activity.resultant_state = 'RUNNING'
def _operation(self, activity, user, system):
self.instance._schedule_vm(activity)
def _operation(self, activity, user, system, timeout=15):
# Allocate VNC port and host node
self.instance.allocate_vnc_port()
self.instance.allocate_node()
# Deploy virtual images
with activity.sub_activity('deploying_disks'):
devnums = list(ascii_lowercase) # a-z
for disk in self.instance.disks.all():
# assign device numbers
if disk.dev_num in devnums:
devnums.remove(disk.dev_num)
else:
disk.dev_num = devnums.pop(0)
disk.save()
# deploy disk
disk.deploy()
self.instance.deploy_disks()
# Deploy VM on remote machine
with activity.sub_activity('deploying_vm') as deploy_act:
deploy_act.result = self.instance.deploy_vm(timeout=timeout)
# Establish network connection (vmdriver)
with activity.sub_activity('deploying_net'):
self.instance.deploy_net()
# Resume vm
with activity.sub_activity('booting'):
self.instance.resume_vm(timeout=timeout)
self.instance._deploy_vm(activity)
self.instance.renew(which='both', base_activity=activity)
register_instance_operation(DeployOperation)
......@@ -103,14 +106,27 @@ class DestroyOperation(InstanceOperation):
def _operation(self, activity, user, system):
if self.instance.node:
self.instance._destroy_vm(activity)
# Destroy networks
with activity.sub_activity('destroying_net'):
self.instance.destroy_net()
# Delete virtual machine
with activity.sub_activity('destroying_vm'):
self.instance.delete_vm()
# Destroy disks
with activity.sub_activity('destroying_disks'):
for disk in self.instance.disks.all():
disk.destroy()
self.instance.destroy_disks()
self.instance._cleanup_after_destroy_vm(activity)
# Delete mem. dump if exists
try:
self.instance.delete_mem_dump()
except:
pass
# Clear node and VNC port association
self.instance.yield_node()
self.instance.yield_vnc_port()
self.instance.destroyed_at = timezone.now()
self.instance.save()
......@@ -131,23 +147,19 @@ class MigrateOperation(InstanceOperation):
to_node = self.instance.select_node()
sa.result = to_node
# Destroy networks
with activity.sub_activity('destroying_net'):
for net in self.instance.interface_set.all():
net.shutdown()
# Shutdown networks
with activity.sub_activity('shutdown_net'):
self.instance.shutdown_net()
with activity.sub_activity('migrate_vm'):
queue_name = self.instance.get_remote_queue_name('vm')
vm_tasks.migrate.apply_async(args=[self.instance.vm_name,
to_node.host.hostname],
queue=queue_name).get(timeout=timeout)
self.instance.migrate_vm(to_node=to_node, timeout=timeout)
# Refresh node information
self.instance.node = to_node
self.instance.save()
# Estabilish network connection (vmdriver)
with activity.sub_activity('deploying_net'):
for net in self.instance.interface_set.all():
net.deploy()
self.instance.deploy_net()
register_instance_operation(MigrateOperation)
......@@ -160,9 +172,7 @@ class RebootOperation(InstanceOperation):
description = _("Reboot virtual machine with Ctrl+Alt+Del signal.")
def _operation(self, activity, user, system, timeout=5):
queue_name = self.instance.get_remote_queue_name('vm')
vm_tasks.reboot.apply_async(args=[self.instance.vm_name],
queue=queue_name).get(timeout=timeout)
self.instance.reboot_vm(timeout=timeout)
register_instance_operation(RebootOperation)
......@@ -175,10 +185,7 @@ class ResetOperation(InstanceOperation):
description = _("Reset virtual machine (reset button).")
def _operation(self, activity, user, system, timeout=5):
queue_name = self.instance.get_remote_queue_name('vm')
vm_tasks.reset.apply_async(args=[self.instance.vm_name],
queue=queue_name).get(timeout=timeout)
self.instance.reset_vm(timeout=timeout)
register_instance_operation(ResetOperation)
......@@ -219,7 +226,7 @@ class SaveAsTemplateOperation(InstanceOperation):
def __try_save_disk(disk):
try:
return disk.save_as() # can do in parallel
return disk.save_as()
except Disk.WrongDiskTypeError:
return disk
......@@ -260,14 +267,9 @@ class ShutdownOperation(InstanceOperation):
activity.resultant_state = 'STOPPED'
def _operation(self, activity, user, system, timeout=120):
queue_name = self.instance.get_remote_queue_name('vm')
logger.debug("RPC Shutdown at queue: %s, for vm: %s.", queue_name,
self.instance.vm_name)
vm_tasks.shutdown.apply_async(kwargs={'name': self.instance.vm_name},
queue=queue_name).get(timeout=timeout)
self.instance.node = None
self.instance.vnc_port = None
self.instance.save()
self.instance.shutdown_vm(timeout=timeout)
self.instance.yield_node()
self.instance.yield_vnc_port()
register_instance_operation(ShutdownOperation)
......@@ -283,12 +285,17 @@ class ShutOffOperation(InstanceOperation):
activity.resultant_state = 'STOPPED'
def _operation(self, activity, user, system):
# Destroy VM
if self.instance.node:
self.instance._destroy_vm(activity)
# Shutdown networks
with activity.sub_activity('shutdown_net'):
self.instance.shutdown_net()
self.instance._cleanup_after_destroy_vm(activity)
self.instance.save()
# Delete virtual machine
with activity.sub_activity('delete_vm'):
self.instance.delete_vm()
# Clear node and VNC port association
self.instance.yield_node()
self.instance.yield_vnc_port()
register_instance_operation(ShutOffOperation)
......@@ -316,18 +323,15 @@ class SleepOperation(InstanceOperation):
def _operation(self, activity, user, system, timeout=60):
# Destroy networks
with activity.sub_activity('destroying_net'):
for net in self.instance.interface_set.all():
net.shutdown()
with activity.sub_activity('shutdown_net'):
self.instance.shutdown_net()
# Suspend vm
with activity.sub_activity('suspending'):
queue_name = self.instance.get_remote_queue_name('vm')
vm_tasks.sleep.apply_async(args=[self.instance.vm_name,
self.instance.mem_dump['path']],
queue=queue_name).get(timeout=timeout)
self.instance.node = None
self.instance.save()
self.instance.suspend_vm(timeout=timeout)
self.instance.yield_node()
# VNC port needs to be kept
register_instance_operation(SleepOperation)
......@@ -355,19 +359,16 @@ class WakeUpOperation(InstanceOperation):
def _operation(self, activity, user, system, timeout=60):
# Schedule vm
self.instance._schedule_vm(activity)
queue_name = self.instance.get_remote_queue_name('vm')
self.instance.allocate_vnc_port()
self.instance.allocate_node()
# Resume vm
with activity.sub_activity('resuming'):
vm_tasks.wake_up.apply_async(args=[self.instance.vm_name,
self.instance.mem_dump['path']],
queue=queue_name).get(timeout=timeout)
self.instance.wake_up_vm(timeout=timeout)
# Estabilish network connection (vmdriver)
with activity.sub_activity('deploying_net'):
for net in self.instance.interface_set.all():
net.deploy()
self.instance.deploy_net()
# Renew vm
self.instance.renew(which='both', base_activity=activity)
......
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