1 # -*- coding: utf-8 -*-
4 from datetime import datetime
5 from random import SystemRandom
6 from django.db import models
7 from django.contrib.auth.models import get_hexdigest
8 from django.utils import html
10 from ais.common import Nmea, mmsi_to_strmmsi, nice_timedelta_str
12 class UserMessageCategory(models.Model):
13 id = models.CharField(max_length=10, primary_key=True)
15 db_table = u'user_message_category'
17 class UserMessage(models.Model):
18 id = models.AutoField(primary_key=True)
19 user = models.ForeignKey('User')
20 category = models.ForeignKey(UserMessageCategory, db_column='user_message_category_id')
21 txt = models.TextField()
23 db_table = u'user_message'
25 class User(models.Model):
26 id = models.AutoField(primary_key=True)
27 login = models.CharField(max_length=16, unique=True)
28 password_hash = models.CharField(max_length=75)
29 name = models.CharField(max_length=50)
30 email = models.EmailField()
31 father = models.ForeignKey('User')
32 creation_datetime = models.DateTimeField(auto_now_add=True)
33 phone = models.CharField(max_length=20, blank=True)
34 access_datetime = models.DateTimeField(blank=True, null=True)
39 def __unicode__(self):
42 def set_password(self, raw_password):
45 salt = get_hexdigest(algo, str(random.random()), str(random.random()))[:5]
46 hsh = get_hexdigest(algo, salt, raw_password)
47 self.password_hash = '%s$%s$%s' % (algo, salt, hsh)
48 self.info('Password changed') # FIXME
50 def check_password(self, raw_password):
51 algo, salt, hsh = self.password_hash.split('$')
52 return hsh == get_hexdigest(algo, salt, raw_password)
55 def update_access_datetime(self):
56 self.access_datetime = datetime.utcnow()
59 def get_and_delete_messages(self):
62 def is_admin_by(self, user_id):
63 if self.id == user_id:
65 if self.father_id is None:
67 return self.father.is_admin_by(user_id)
69 def get_messages(self):
70 messages = UserMessage.objects.filter(user__id = self.id)
72 [ {'category': message.category, \
74 for message in messages \
79 def info(self, message):
80 UserMessage(user_id = self.id, category_id=u'info', txt=html.escape(message)).save()
82 def error(self, message):
83 UserMessage(user_id = self.id, category_id=u'error', txt=html.escape(message)).save()
85 def check_sandbox_access(self, source_user=None):
88 FleetUser.objects.get(fleet = SANDBOX_FLEET, user = self)
89 except FleetUser.DoesNotExist:
92 fu.fleet_id = SANDBOX_FLEET
95 source_user.info("%s was granted access to 'sandbox' fleet" % self.login)
98 class Vessel(models.Model):
99 mmsi = models.IntegerField(primary_key=True)
100 name = models.CharField(max_length=20)
101 imo = models.IntegerField()
102 callsign = models.CharField(max_length=7)
103 type = models.IntegerField(default=0)
104 destination = models.CharField(max_length=20, blank=True, null=True)
105 updated = models.DateTimeField()
106 source = models.CharField(max_length=8)
107 dim_bow = models.IntegerField(default=0)
108 dim_stern = models.IntegerField(default=0)
109 dim_port = models.IntegerField(default=0)
110 dim_starboard = models.IntegerField(default=0)
111 eta = models.CharField(max_length=8, default='00002460') # format MMDDhhmm
114 def __unicode__(self):
115 return unicode(self.mmsi) # FIXME
116 def get_last_nmea(self):
117 strmmsi = mmsi_to_strmmsi(self.mmsi)
118 return Nmea.new_from_lastinfo(strmmsi)
121 class Fleet(models.Model):
122 id = models.AutoField(primary_key=True)
123 name = models.CharField(max_length=50)
124 vessel = models.ManyToManyField(Vessel, through='FleetVessel')
125 description = models.TextField()
128 def __unicode__(self):
130 def vessel_count(self):
131 return FleetVessel.objects.filter(fleet=self.id).count()
132 def user_count(self):
133 return FleetUser.objects.filter(fleet=self.id).count()
135 if os.path.exists('/var/lib/ais/cron/fleets/%s.cron' % self.name):
140 class FleetUser(models.Model):
141 id = models.AutoField(primary_key=True)
142 fleet = models.ForeignKey(Fleet) #, db_column='fleet_id', to_field='id')
143 user = models.ForeignKey(User)
145 db_table = u'fleet_user'
147 class FleetVessel(models.Model):
148 id = models.AutoField(primary_key=True)
149 fleet = models.ForeignKey(Fleet, db_column='fleet_id', to_field='id')
150 vessel = models.ForeignKey(Vessel, db_column='mmsi', to_field='mmsi')
152 db_table = u'fleet_vessel'
154 ## manual input source
155 #class MiSource(models.Model):
156 # id = models.IntegerField(primary_key=True)
157 # userid = models.IntegerField()
158 # name = models.TextField(unique=True)
160 # db_table = u'mi_source'
162 ## manual input vessel
163 #class MiVessel(models.Model):
164 # mmsi_txt = models.TextField(primary_key=True) # This field type is a guess.
166 # db_table = u'mi_vessel'
170 #class Ppuser(models.Model):
171 # usr = models.TextField(primary_key=True) # This field type is a guess.
172 # lat = models.FloatField()
173 # lon = models.FloatField()
175 # db_table = u'ppuser'
177 #class Plane(models.Model):
178 # flight = models.CharField(max_length=8)
179 # reg = models.CharField(max_length=8)
180 # ads = models.CharField(max_length=8)
181 # type = models.CharField(max_length=4)
182 # usr = models.TextField() # This field type is a guess.
183 # updated = models.DateTimeField()
185 # db_table = u'plane'
189 class News(models.Model):
190 id = models.AutoField(primary_key=True)
191 created = models.DateTimeField()
192 updated = models.DateTimeField()
193 title = models.TextField()
194 txt = models.TextField()
199 class Job(models.Model):
200 def make_unique_job_id():
203 source = u'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
206 result += source[int(rnd.random()*len(source))]
208 return make_id() # TODO check it's unique
210 id = models.CharField(primary_key=True, max_length=8, default=make_unique_job_id)
211 user = models.ForeignKey(User)
212 queue_time = models.DateTimeField(auto_now_add=True)
213 start_time = models.DateTimeField(blank=True, null=True)
214 finish_time = models.DateTimeField(blank=True, null=True)
215 command = models.TextField()
216 friendly_filename = models.CharField(max_length=255)
217 pid = models.IntegerField(blank=True, null=True)
218 result = models.IntegerField(blank=True, null=True)
219 archive_time = models.DateTimeField(blank=True, null=True)
221 def queue_rank(self):
222 return Job.objects.filter(queue_time__lt=self.queue_time).filter(start_time__isnull=True).count() + 1
223 def process_time(self):
224 dt = self.finish_time - self.start_time
225 return nice_timedelta_str(dt)
230 strstats = file('/proc/%s/stat' % self.pid).read()
234 strstats = strstats.rstrip('\n').split(' ')
235 for i, key in enumerate(('pid', 'comm', 'state', 'ppid', 'pgrp', 'session', 'tty_nr', 'tpgid', 'flags', 'minflt', 'cminflt', 'majflt', 'cmajflt', 'utime', 'stime', 'cutime', 'cstime', 'priority', 'nice', 'num_threads', 'itrealvalue', 'starttime', 'vsize', 'rss', 'rsslim', 'startcode', 'endcode', 'startstack', 'kstkesp', 'kstkeip', 'signal', 'blocked', 'sigignore', 'sigcatch', 'wchan', 'nswap', 'cnswap', 'exit_signal', 'processor', 'rt_priority', 'policy', 'delayacct_blkio_ticks', 'guest_time', 'cguest_time')):
236 result[key] = strstats[i]
239 def get_sucess_size(self):
240 extension = os.path.splitext(self.friendly_filename)[-1]
241 filename = '/var/lib/ais/jobs/%s%s' % (self.id, extension)
242 return os.path.getsize(filename)
246 ordering = ('queue_time',)