Commit 57863a5b by Kálmán Viktor

Merge branch 'master' into feature-mass-ops

Conflicts:
	circle/vm/operations.py
parents 1197f78d 5ce861b8
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
{% block content %} {% block content %}
<div class="body-content"> <div class="body-content">
<div class="page-header"> <div class="page-header">
<h1> <h1><i class="fa fa-{{icon}}"></i>
{{ object.instance.name }}: {{ object.instance.name }}:
{% if user.is_superuser %} {% if user.is_superuser %}
{{object.readable_name.get_admin_text}} {{object.readable_name.get_admin_text}}
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
{% for a in activities %} {% for a in activities %}
<div class="activity{% if a.pk == active.pk %} activity-active{%endif%}" data-activity-id="{{ a.pk }}"> <div class="activity{% if a.pk == active.pk %} activity-active{%endif%}" data-activity-id="{{ a.pk }}">
<span class="timeline-icon{% if a.has_failed %} timeline-icon-failed{% endif %}"> <span class="timeline-icon{% if a.has_failed %} timeline-icon-failed{% endif %}">
<i class="fa {% if not a.finished %}fa-refresh fa-spin {% else %}fa-plus{% endif %}"></i> <i class="fa {% if not a.finished %}fa-refresh fa-spin {% else %}fa-{{a.icon}}{% endif %}"></i>
</span> </span>
<strong{% if a.result %} title="{{ a.result.get_user_text }}"{% endif %}> <strong{% if a.result %} title="{{ a.result.get_user_text }}"{% endif %}>
<a href="{{ a.get_absolute_url }}"> <a href="{{ a.get_absolute_url }}">
......
...@@ -309,7 +309,7 @@ class VmDetailView(CheckedDetailView): ...@@ -309,7 +309,7 @@ class VmDetailView(CheckedDetailView):
activities = instance.get_merged_activities(user) activities = instance.get_merged_activities(user)
show_show_all = len(activities) > 10 show_show_all = len(activities) > 10
activities = activities[:10] activities = activities[:10]
context['activities'] = activities context['activities'] = _format_activities(activities)
context['show_show_all'] = show_show_all context['show_show_all'] = show_show_all
latest = instance.get_latest_activity_in_progress() latest = instance.get_latest_activity_in_progress()
context['is_new_state'] = (latest and context['is_new_state'] = (latest and
...@@ -2625,7 +2625,8 @@ def vm_activity(request, pk): ...@@ -2625,7 +2625,8 @@ def vm_activity(request, pk):
response = {} response = {}
show_all = request.GET.get("show_all", "false") == "true" show_all = request.GET.get("show_all", "false") == "true"
activities = instance.get_merged_activities(request.user) activities = _format_activities(
instance.get_merged_activities(request.user))
show_show_all = len(activities) > 10 show_show_all = len(activities) > 10
if not show_all: if not show_all:
activities = activities[:10] activities = activities[:10]
...@@ -3082,6 +3083,20 @@ def get_disk_download_status(request, pk): ...@@ -3082,6 +3083,20 @@ def get_disk_download_status(request, pk):
) )
def _get_activity_icon(act):
op = act.get_operation()
if op and op.id in vm_ops:
return vm_ops[op.id].icon
else:
return "cog"
def _format_activities(acts):
for i in acts:
i.icon = _get_activity_icon(i)
return acts
class InstanceActivityDetail(CheckedDetailView): class InstanceActivityDetail(CheckedDetailView):
model = InstanceActivity model = InstanceActivity
context_object_name = 'instanceactivity' # much simpler to mock object context_object_name = 'instanceactivity' # much simpler to mock object
...@@ -3092,8 +3107,9 @@ class InstanceActivityDetail(CheckedDetailView): ...@@ -3092,8 +3107,9 @@ class InstanceActivityDetail(CheckedDetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
ctx = super(InstanceActivityDetail, self).get_context_data(**kwargs) ctx = super(InstanceActivityDetail, self).get_context_data(**kwargs)
ctx['activities'] = self.object.instance.get_activities( ctx['activities'] = _format_activities(
self.request.user) self.object.instance.get_activities(self.request.user))
ctx['icon'] = _get_activity_icon(self.object)
return ctx return ctx
......
...@@ -192,6 +192,10 @@ class InstanceActivity(ActivityModel): ...@@ -192,6 +192,10 @@ class InstanceActivity(ActivityModel):
readable_name=readable_name) readable_name=readable_name)
return activitycontextimpl(act, on_abort=on_abort, on_commit=on_commit) return activitycontextimpl(act, on_abort=on_abort, on_commit=on_commit)
def get_operation(self):
return self.instance.get_operation_from_activity_code(
self.activity_code)
@contextmanager @contextmanager
def instance_activity(code_suffix, instance, on_abort=None, on_commit=None, def instance_activity(code_suffix, instance, on_abort=None, on_commit=None,
......
...@@ -32,6 +32,7 @@ from django.core.exceptions import PermissionDenied ...@@ -32,6 +32,7 @@ from django.core.exceptions import PermissionDenied
from django.db.models import (BooleanField, CharField, DateTimeField, from django.db.models import (BooleanField, CharField, DateTimeField,
IntegerField, ForeignKey, Manager, IntegerField, ForeignKey, Manager,
ManyToManyField, permalink, SET_NULL, TextField) ManyToManyField, permalink, SET_NULL, TextField)
from django.db import IntegrityError
from django.dispatch import Signal from django.dispatch import Signal
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _, ugettext_noop from django.utils.translation import ugettext_lazy as _, ugettext_noop
...@@ -926,8 +927,16 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin, ...@@ -926,8 +927,16 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
def allocate_vnc_port(self): def allocate_vnc_port(self):
if self.vnc_port is None: if self.vnc_port is None:
self.vnc_port = find_unused_vnc_port() while True:
self.save() try:
self.vnc_port = find_unused_vnc_port()
self.save()
except IntegrityError:
# Another thread took this port get another one
logger.debug("Port %s is in use.", self.vnc_port)
pass
else:
break
def yield_vnc_port(self): def yield_vnc_port(self):
if self.vnc_port is not None: if self.vnc_port is not None:
......
...@@ -260,6 +260,16 @@ class DeployOperation(InstanceOperation): ...@@ -260,6 +260,16 @@ class DeployOperation(InstanceOperation):
self.instance.STATUS.PENDING, self.instance.STATUS.PENDING,
self.instance.STATUS.ERROR) self.instance.STATUS.ERROR)
def on_abort(self, activity, error):
activity.resultant_state = 'STOPPED'
def on_commit(self, activity):
activity.resultant_state = 'RUNNING'
activity.result = create_readable(
ugettext_noop("virtual machine successfully "
"deployed to node: %(node)s"),
node=self.instance.node)
def _operation(self, activity, timeout=15): def _operation(self, activity, timeout=15):
# Allocate VNC port and host node # Allocate VNC port and host node
self.instance.allocate_vnc_port() self.instance.allocate_vnc_port()
...@@ -273,9 +283,11 @@ class DeployOperation(InstanceOperation): ...@@ -273,9 +283,11 @@ class DeployOperation(InstanceOperation):
# Deploy VM on remote machine # Deploy VM on remote machine
if self.instance.state not in ['PAUSED']: if self.instance.state not in ['PAUSED']:
rn = create_readable(ugettext_noop("deploy virtual machine"),
ugettext_noop("deploy vm to %(node)s"),
node=self.instance.node)
with activity.sub_activity( with activity.sub_activity(
'deploying_vm', readable_name=ugettext_noop( 'deploying_vm', readable_name=rn) as deploy_act:
"deploy virtual machine")) as deploy_act:
deploy_act.result = self.instance.deploy_vm(timeout=timeout) deploy_act.result = self.instance.deploy_vm(timeout=timeout)
# Establish network connection (vmdriver) # Establish network connection (vmdriver)
......
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