Commit 41f26955 by Őry Máté

vm: add StatusModel to Instance

parent ab7f53b9
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
{% elif node.state == 'MISSING' %}label-danger {% elif node.state == 'MISSING' %}label-danger
{% elif node.state == 'DISABLED' %}label-warning {% elif node.state == 'DISABLED' %}label-warning
{% elif node.state == 'OFFLINE' %}label-warning {% elif node.state == 'OFFLINE' %}label-warning
{% endif %}">{{ node.state }}</span> {% endif %}">{{ node.get_status_display|upper }}</span>
<div class="btn-group"> <div class="btn-group">
<button type="button" class="btn {{ btn_size }} btn-warning nojs-dropdown-toogle dropdown-toggle" data-toggle="dropdown">Action <i class="icon-caret-down"></i></button> <button type="button" class="btn {{ btn_size }} btn-warning nojs-dropdown-toogle dropdown-toggle" data-toggle="dropdown">Action <i class="icon-caret-down"></i></button>
<ul class="dropdown-menu nojs-dropdown-toogle" role="menu"> <ul class="dropdown-menu nojs-dropdown-toogle" role="menu">
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
<tr class="{% cycle 'odd' 'even' %}"> <tr class="{% cycle 'odd' 'even' %}">
<td class="pk"><div id="vm-{{i.pk}}">{{i.pk}}</div> </td> <td class="pk"><div id="vm-{{i.pk}}">{{i.pk}}</div> </td>
<td class="name"><a class="real-link" href="{% url "dashboard.views.detail" i.pk %}">{{ i.name }}</a> </td> <td class="name"><a class="real-link" href="{% url "dashboard.views.detail" i.pk %}">{{ i.name }}</a> </td>
<td class="state">{{ i.cached_state }}</td> <td class="state">{{ i.get_status_display }}</td>
<td>{{ i.owner }}</td> <td>{{ i.owner }}</td>
{% if user.is_superuser %}<td>{{ i.node.name|default:"-" }}</td>{% endif %} {% if user.is_superuser %}<td>{{ i.node.name|default:"-" }}</td>{% endif %}
</tr> </tr>
......
...@@ -117,14 +117,13 @@ class IndexView(LoginRequiredMixin, TemplateView): ...@@ -117,14 +117,13 @@ class IndexView(LoginRequiredMixin, TemplateView):
} }
}) })
running = [i for i in instances if i.cached_state == 'RUNNING'] running = instances.filter(status='RUNNING')
stopped = [i for i in instances if i.cached_state not in ['RUNNING', stopped = instances.exclude(status__in=('RUNNING', 'NOSTATE'))
'NOSTATE']]
context.update({ context.update({
'running_vms': running, 'running_vms': running[:20],
'running_vm_num': len(running), 'running_vm_num': running.count(),
'stopped_vm_num': len(stopped) 'stopped_vm_num': stopped.count()
}) })
context['templates'] = InstanceTemplate.objects.all()[:5] context['templates'] = InstanceTemplate.objects.all()[:5]
......
...@@ -79,6 +79,11 @@ class InstanceActivity(ActivityModel): ...@@ -79,6 +79,11 @@ class InstanceActivity(ActivityModel):
act = self.create_sub(code_suffix, task_uuid) act = self.create_sub(code_suffix, task_uuid)
return activitycontextimpl(act, on_abort=on_abort, on_commit=on_commit) return activitycontextimpl(act, on_abort=on_abort, on_commit=on_commit)
def save(self, *args, **kwargs):
ret = super(InstanceActivity, self).save(*args, **kwargs)
self.instance._update_status()
return ret
@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,
......
...@@ -2,6 +2,7 @@ from __future__ import absolute_import, unicode_literals ...@@ -2,6 +2,7 @@ from __future__ import absolute_import, unicode_literals
from datetime import timedelta from datetime import timedelta
from logging import getLogger from logging import getLogger
from importlib import import_module from importlib import import_module
from warnings import warn
import string import string
import django.conf import django.conf
...@@ -16,7 +17,8 @@ from django.utils import timezone ...@@ -16,7 +17,8 @@ from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from celery.exceptions import TimeLimitExceeded from celery.exceptions import TimeLimitExceeded
from model_utils.models import TimeStampedModel from model_utils import Choices
from model_utils.models import TimeStampedModel, StatusModel
from taggit.managers import TaggableManager from taggit.managers import TaggableManager
from acl.models import AclBase from acl.models import AclBase
...@@ -25,7 +27,6 @@ from ..tasks import local_tasks, vm_tasks, agent_tasks ...@@ -25,7 +27,6 @@ from ..tasks import local_tasks, vm_tasks, agent_tasks
from .activity import (ActivityInProgressError, instance_activity, from .activity import (ActivityInProgressError, instance_activity,
InstanceActivity) InstanceActivity)
from .common import BaseResourceConfigModel, Lease from .common import BaseResourceConfigModel, Lease
from common.models import method_cache
from .network import Interface from .network import Interface
from .node import Node, Trait from .node import Node, Trait
...@@ -162,7 +163,8 @@ class InstanceTemplate(AclBase, VirtualMachineDescModel, TimeStampedModel): ...@@ -162,7 +163,8 @@ class InstanceTemplate(AclBase, VirtualMachineDescModel, TimeStampedModel):
return ('dashboard.views.template-detail', None, {'pk': self.pk}) return ('dashboard.views.template-detail', None, {'pk': self.pk})
class Instance(AclBase, VirtualMachineDescModel, TimeStampedModel): class Instance(AclBase, VirtualMachineDescModel, StatusModel,
TimeStampedModel):
"""Virtual machine instance. """Virtual machine instance.
""" """
...@@ -171,6 +173,15 @@ class Instance(AclBase, VirtualMachineDescModel, TimeStampedModel): ...@@ -171,6 +173,15 @@ class Instance(AclBase, VirtualMachineDescModel, TimeStampedModel):
('operator', _('operator')), # console, networking, change state ('operator', _('operator')), # console, networking, change state
('owner', _('owner')), # superuser, can delete, delegate perms ('owner', _('owner')), # superuser, can delete, delegate perms
) )
STATUS = Choices(
('NOSTATE', _('no state')),
('RUNNING', _('running')),
('STOPPED', _('stopped')),
('SUSPENDED', _('suspended')),
('ERROR', _('error')),
('PENDING', _('pending')),
('DESTROYED', _('destroyed')),
)
name = CharField(blank=True, max_length=100, verbose_name=_('name'), name = CharField(blank=True, max_length=100, verbose_name=_('name'),
help_text=_("Human readable name of instance.")) help_text=_("Human readable name of instance."))
description = TextField(blank=True, verbose_name=_('description')) description = TextField(blank=True, verbose_name=_('description'))
...@@ -258,13 +269,23 @@ class Instance(AclBase, VirtualMachineDescModel, TimeStampedModel): ...@@ -258,13 +269,23 @@ class Instance(AclBase, VirtualMachineDescModel, TimeStampedModel):
return self.state == 'RUNNING' return self.state == 'RUNNING'
@property @property
@method_cache(10, 5)
def cached_state(self):
return self.state
@property
def state(self): def state(self):
"""State of the virtual machine instance. warn('Use Instance.status (or get_status_display) instead.',
DeprecationWarning)
return self.status
def _update_status(self):
"""Set the proper status of the instance to Instance.status.
"""
old = self.status
self.status = self._compute_status()
if old != self.status:
logger.info('Status of Instance#%d changed to %s',
self.pk, self.status)
self.save()
def _compute_status(self):
"""Return the proper status of the instance based on activities.
""" """
# check special cases # check special cases
if self.activity_log.filter(activity_code__endswith='migrate', if self.activity_log.filter(activity_code__endswith='migrate',
......
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