Commit f3aa35f9 by Dudás Ádám

storage, vm: change activity log format to hierarchical

parent 8cd8d2bf
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Deleting field 'DiskActivity.state'
db.delete_column(u'storage_diskactivity', 'state')
# Adding field 'DiskActivity.parent'
db.add_column(u'storage_diskactivity', 'parent',
self.gf('django.db.models.fields.related.ForeignKey')(to=orm['storage.DiskActivity'], null=True, blank=True),
keep_default=False)
def backwards(self, orm):
# Adding field 'DiskActivity.state'
db.add_column(u'storage_diskactivity', 'state',
self.gf('django.db.models.fields.CharField')(default='PENDING', max_length=50),
keep_default=False)
# Deleting field 'DiskActivity.parent'
db.delete_column(u'storage_diskactivity', 'parent_id')
models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'storage.datastore': {
'Meta': {'ordering': "['name']", 'object_name': 'DataStore'},
'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'})
},
u'storage.disk': {
'Meta': {'ordering': "['name']", 'object_name': 'Disk'},
'base': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'derivatives'", 'null': 'True', 'to': u"orm['storage.Disk']"}),
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'datastore': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['storage.DataStore']"}),
'destroyed': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
'dev_num': ('django.db.models.fields.CharField', [], {'default': "'a'", 'max_length': '1'}),
'filename': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'ready': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'size': ('sizefield.models.FileSizeField', [], {}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '10'})
},
u'storage.diskactivity': {
'Meta': {'object_name': 'DiskActivity'},
'activity_code': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'disk': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_log'", 'to': u"orm['storage.Disk']"}),
'finished': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['storage.DiskActivity']", 'null': 'True', 'blank': 'True'}),
'result': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'started': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'task_uuid': ('django.db.models.fields.CharField', [], {'max_length': '50', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'})
}
}
complete_apps = ['storage']
\ No newline at end of file
# coding=utf-8 # coding=utf-8
from contextlib import contextmanager
import logging import logging
import uuid import uuid
from django.contrib.auth.models import User
from django.db.models import (Model, BooleanField, CharField, DateTimeField, from django.db.models import (Model, BooleanField, CharField, DateTimeField,
ForeignKey, TextField) ForeignKey)
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from model_utils.models import TimeStampedModel from model_utils.models import TimeStampedModel
from sizefield.models import FileSizeField from sizefield.models import FileSizeField
from .tasks import local_tasks, remote_tasks from .tasks import local_tasks, remote_tasks
from common.models import ActivityModel, activitycontextimpl
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -160,30 +161,24 @@ class Disk(TimeStampedModel): ...@@ -160,30 +161,24 @@ class Disk(TimeStampedModel):
if self.ready: if self.ready:
return False return False
act = DiskActivity(activity_code='storage.Disk.deploy') with disk_activity(code_suffix='deploy', disk=self,
act.disk = self task_uuid=task_uuid, user=user) as act:
act.started = timezone.now()
act.state = 'PENDING'
act.task_uuid = task_uuid
act.user = user
act.save()
# Delegate create / snapshot jobs # Delegate create / snapshot jobs
queue_name = self.datastore.hostname + ".storage" queue_name = self.datastore.hostname + ".storage"
disk_desc = self.get_disk_desc() disk_desc = self.get_disk_desc()
if self.type == 'qcow2-snap': if self.type == 'qcow2-snap':
act.update_state('CREATING SNAPSHOT') with act.sub_activity('creating_snapshot'):
remote_tasks.snapshot.apply_async(args=[disk_desc], remote_tasks.snapshot.apply_async(args=[disk_desc],
queue=queue_name).get() queue=queue_name).get()
else: else:
act.update_state('CREATING DISK') with act.sub_activity('creating_disk'):
remote_tasks.create.apply_async(args=[disk_desc], remote_tasks.create.apply_async(args=[disk_desc],
queue=queue_name).get() queue=queue_name).get()
self.ready = True self.ready = True
self.save() self.save()
act.finish('SUCCESS')
return True return True
def deploy_async(self, user=None): def deploy_async(self, user=None):
...@@ -224,13 +219,8 @@ class Disk(TimeStampedModel): ...@@ -224,13 +219,8 @@ class Disk(TimeStampedModel):
# from this point on, the caller has to guarantee that the disk is not # from this point on, the caller has to guarantee that the disk is not
# going to be used until the operation is complete # going to be used until the operation is complete
act = DiskActivity(activity_code='storage.Disk.save_as') with disk_activity(code_suffix='save_as', disk=self,
act.disk = self task_uuid=task_uuid, user=user):
act.started = timezone.now()
act.state = 'PENDING'
act.task_uuid = task_uuid
act.user = user
act.save()
filename = str(uuid.uuid4()) filename = str(uuid.uuid4())
new_type, new_base = mapping[self.type] new_type, new_base = mapping[self.type]
...@@ -246,31 +236,38 @@ class Disk(TimeStampedModel): ...@@ -246,31 +236,38 @@ class Disk(TimeStampedModel):
disk.ready = True disk.ready = True
disk.save() disk.save()
act.finish('SUCCESS')
return disk return disk
class DiskActivity(TimeStampedModel): class DiskActivity(ActivityModel):
activity_code = CharField(verbose_name=_('activity_code'), max_length=100) disk = ForeignKey(Disk, related_name='activity_log',
task_uuid = CharField(verbose_name=_('task_uuid'), blank=True, help_text=_('Disk this activity works on.'),
max_length=50, null=True, unique=True) verbose_name=_('disk'))
disk = ForeignKey(Disk, verbose_name=_('disk'),
related_name='activity_log')
user = ForeignKey(User, verbose_name=_('user'), blank=True, null=True)
started = DateTimeField(verbose_name=_('started'), blank=True, null=True)
finished = DateTimeField(verbose_name=_('finished'), blank=True, null=True)
result = TextField(verbose_name=_('result'), blank=True, null=True)
state = CharField(verbose_name=_('state'), default='PENDING',
max_length=50)
def update_state(self, new_state):
self.state = new_state
self.save()
def finish(self, result=None): @classmethod
if not self.finished: def create(cls, code_suffix, instance, task_uuid=None, user=None):
self.finished = timezone.now() act = cls(activity_code='storage.Disk.' + code_suffix,
self.result = result instance=instance, parent=None, started=timezone.now(),
self.state = 'COMPLETED' task_uuid=task_uuid, user=user)
self.save() act.save()
return act
def create_sub(self, code_suffix, task_uuid=None):
act = DiskActivity(
activity_code=self.activity_code + '.' + code_suffix,
instance=self.instance, parent=self, started=timezone.now(),
task_uuid=task_uuid, user=self.user)
act.save()
return act
@contextmanager
def sub_activity(self, code_suffix, task_uuid=None):
act = self.create_sub(code_suffix, task_uuid)
activitycontextimpl(act)
@contextmanager
def disk_activity(code_suffix, instance, task_uuid=None, user=None):
act = DiskActivity.create(code_suffix, instance, task_uuid, user)
activitycontextimpl(act)
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