Statistics
| Branch: | Tag: | Revision:

root / db / models.py @ b8d1a948

History | View | Annotate | Download (17.6 kB)

1 46547e14 Faidon Liambotis
# vim: ts=4 sts=4 et ai sw=4 fileencoding=utf-8
2 48130e66 Georgios Gousios
# Copyright 2011 GRNET S.A. All rights reserved.
3 48130e66 Georgios Gousios
#
4 48130e66 Georgios Gousios
# Redistribution and use in source and binary forms, with or without
5 48130e66 Georgios Gousios
# modification, are permitted provided that the following conditions
6 48130e66 Georgios Gousios
# are met:
7 48130e66 Georgios Gousios
#
8 48130e66 Georgios Gousios
#   1. Redistributions of source code must retain the above copyright
9 48130e66 Georgios Gousios
#      notice, this list of conditions and the following disclaimer.
10 48130e66 Georgios Gousios
#
11 48130e66 Georgios Gousios
#  2. Redistributions in binary form must reproduce the above copyright
12 48130e66 Georgios Gousios
#     notice, this list of conditions and the following disclaimer in the
13 48130e66 Georgios Gousios
#     documentation and/or other materials provided with the distribution.
14 48130e66 Georgios Gousios
#
15 48130e66 Georgios Gousios
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
16 48130e66 Georgios Gousios
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 48130e66 Georgios Gousios
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 48130e66 Georgios Gousios
# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
19 48130e66 Georgios Gousios
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 48130e66 Georgios Gousios
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 48130e66 Georgios Gousios
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 48130e66 Georgios Gousios
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 48130e66 Georgios Gousios
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 48130e66 Georgios Gousios
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 48130e66 Georgios Gousios
# SUCH DAMAGE.
26 48130e66 Georgios Gousios
#
27 48130e66 Georgios Gousios
# The views and conclusions contained in the software and documentation are
28 48130e66 Georgios Gousios
# those of the authors and should not be interpreted as representing official
29 48130e66 Georgios Gousios
# policies, either expressed or implied, of GRNET S.A.
30 48130e66 Georgios Gousios
31 46547e14 Faidon Liambotis
32 9dbe70f8 Markos Gogoulos
from django.conf import settings
33 17935f41 Vassilios Karakoidas
from django.db import models
34 7b7f9205 Vassilios Karakoidas
35 38684389 Markos Gogoulos
import datetime
36 f5ad2956 Markos Gogoulos
37 d08a5f6f Vangelis Koukis
class SynnefoUser(models.Model):
38 420f2c20 Georgios Gousios
39 76cc889c Georgios Gousios
    #TODO: Amend this when we have groups
40 420f2c20 Georgios Gousios
    ACCOUNT_TYPE = (
41 420f2c20 Georgios Gousios
        ('STUDENT', 'Student'),
42 84ae2c4c Georgios Gousios
        ('PROFESSOR', 'Professor'),
43 5ac53b64 Georgios Gousios
        ('USER', 'Generic User'),
44 5ac53b64 Georgios Gousios
        ('HELPDESK', 'Helpdesk User')
45 420f2c20 Georgios Gousios
    )
46 420f2c20 Georgios Gousios
47 cfe9f88c Georgios Gousios
    name = models.CharField('Synnefo Username', max_length=255, default='')
48 cfe9f88c Georgios Gousios
    realname = models.CharField('Real Name', max_length=255, default='')
49 cfe9f88c Georgios Gousios
    uniq = models.CharField('External Unique ID', max_length=255,null=True)
50 bf48028e Vassilios Karakoidas
    credit = models.IntegerField('Credit Balance')
51 1896d262 Georgios Gousios
    auth_token = models.CharField('Authentication Token', max_length=32, null=True)
52 c9fdfa27 Georgios Gousios
    auth_token_created = models.DateTimeField('Time of auth token creation', auto_now_add=True, null = True)
53 c9fdfa27 Georgios Gousios
    auth_token_expires = models.DateTimeField('Time of auth token expiration', auto_now_add=True, null = True)
54 badc49b3 Georgios Gousios
    tmp_auth_token = models.CharField('Temporary authentication token', max_length=32, null=True)
55 badc49b3 Georgios Gousios
    tmp_auth_token_expires = models.DateTimeField('Time of temporary auth token expiration', auto_now_add=True, null = True)
56 b8d1a948 Giorgos Verigakis
    type = models.CharField('Account type', choices=ACCOUNT_TYPE,
57 b8d1a948 Giorgos Verigakis
                            max_length=30)
58 52194743 Vangelis Koukis
    created = models.DateTimeField('Time of creation', auto_now_add=True)
59 52194743 Vangelis Koukis
    updated = models.DateTimeField('Time of last update', auto_now=True)
60 33e00f02 Georgios Gousios
    max_invitations = models.IntegerField('Max number of invitations',
61 33e00f02 Georgios Gousios
                                          null=True)
62 92c53da1 Vassilios Karakoidas
63 be7b8d37 Vassilios Karakoidas
    class Meta:
64 d08a5f6f Vangelis Koukis
        verbose_name = u'Synnefo User'
65 420f2c20 Georgios Gousios
66 46547e14 Faidon Liambotis
    def __unicode__(self):
67 ef39e7ee Georgios Gousios
        return self.name
68 07f3219d Vassilios Karakoidas
69 1583f11a Vassilios Karakoidas
    def get_limit(self, limit_name):
70 1583f11a Vassilios Karakoidas
        """Returns the limit value for the specified limit"""
71 6bffabbd Vassilios Karakoidas
        limit_objs = Limit.objects.filter(name=limit_name, user=self)
72 1583f11a Vassilios Karakoidas
        if len(limit_objs) == 1:
73 1583f11a Vassilios Karakoidas
            return limit_objs[0].value
74 1583f11a Vassilios Karakoidas
        
75 1583f11a Vassilios Karakoidas
        return 0
76 bf48028e Vassilios Karakoidas
        
77 bf48028e Vassilios Karakoidas
    def _get_credit_quota(self):
78 bf48028e Vassilios Karakoidas
        """Internal getter function for credit quota"""
79 bf48028e Vassilios Karakoidas
        return self.get_limit('QUOTA_CREDIT')
80 bf48028e Vassilios Karakoidas
        
81 bf48028e Vassilios Karakoidas
    credit_quota = property(_get_credit_quota)
82 bf48028e Vassilios Karakoidas
    
83 bf48028e Vassilios Karakoidas
    def _get_monthly_rate(self):
84 bf48028e Vassilios Karakoidas
        """Internal getter function for monthly credit issue rate"""
85 bf48028e Vassilios Karakoidas
        return self.get_limit('MONTHLY_RATE')
86 bf48028e Vassilios Karakoidas
        
87 bf48028e Vassilios Karakoidas
    monthly_rate = property(_get_monthly_rate)
88 bf48028e Vassilios Karakoidas
    
89 d174b105 Vassilios Karakoidas
    def _get_min_credits(self):
90 bf48028e Vassilios Karakoidas
        """Internal getter function for maximum number of violations"""
91 d174b105 Vassilios Karakoidas
        return self.get_limit('MIN_CREDITS')
92 bf48028e Vassilios Karakoidas
        
93 d174b105 Vassilios Karakoidas
    min_credits = property(_get_min_credits)
94 b1699441 Vassilios Karakoidas
95 0b5a51f7 Vassilios Karakoidas
96 6496c622 Vassilios Karakoidas
class Image(models.Model):
97 6496c622 Vassilios Karakoidas
    # This is WIP, FIXME
98 6496c622 Vassilios Karakoidas
    IMAGE_STATES = (
99 b4808d2b Vassilios Karakoidas
        ('ACTIVE', 'Active'),
100 b4808d2b Vassilios Karakoidas
        ('SAVING', 'Saving'),
101 b4808d2b Vassilios Karakoidas
        ('DELETED', 'Deleted')
102 6496c622 Vassilios Karakoidas
    )
103 6496c622 Vassilios Karakoidas
104 b7d29d41 Constantinos Venetsanopoulos
    # The list of supported Image formats
105 b7d29d41 Constantinos Venetsanopoulos
    FORMATS = (
106 27ccb60f Constantinos Venetsanopoulos
        ('dump', 'ext3 dump'),
107 27ccb60f Constantinos Venetsanopoulos
        ('lvm', 'lvm snapshot'),
108 27ccb60f Constantinos Venetsanopoulos
        ('ntfsclone', 'Windows Image produced by ntfsclone')
109 b7d29d41 Constantinos Venetsanopoulos
    )
110 b7d29d41 Constantinos Venetsanopoulos
111 13b3c5ff Vassilios Karakoidas
    name = models.CharField('Image name', max_length=255)
112 a191bd4d Giorgos Verigakis
    state = models.CharField('Current Image State', choices=IMAGE_STATES,
113 a191bd4d Giorgos Verigakis
                                max_length=30)
114 a0d4498a Vangelis Koukis
    owner = models.ForeignKey(SynnefoUser, blank=True, null=True)
115 52194743 Vangelis Koukis
    created = models.DateTimeField('Time of creation', auto_now_add=True)
116 52194743 Vangelis Koukis
    updated = models.DateTimeField('Time of last update', auto_now=True)
117 b4808d2b Vassilios Karakoidas
    sourcevm = models.ForeignKey("VirtualMachine", null=True)
118 b7d29d41 Constantinos Venetsanopoulos
    backend_id = models.CharField(max_length=50, default='debian_base')
119 b7d29d41 Constantinos Venetsanopoulos
    format = models.CharField(choices=FORMATS, max_length=30, default='dump')
120 75768d0e Giorgos Verigakis
    public = models.BooleanField(default=False)
121 6496c622 Vassilios Karakoidas
122 6496c622 Vassilios Karakoidas
    class Meta:
123 6496c622 Vassilios Karakoidas
        verbose_name = u'Image'
124 6496c622 Vassilios Karakoidas
125 6496c622 Vassilios Karakoidas
    def __unicode__(self):
126 452d2391 Vassilios Karakoidas
        return u'%s' % ( self.name, )
127 6496c622 Vassilios Karakoidas
128 53827f6d Markos Gogoulos
129 53827f6d Markos Gogoulos
class ImageMetadata(models.Model):
130 13b3c5ff Vassilios Karakoidas
    meta_key = models.CharField('Image metadata key name', max_length=50)
131 13b3c5ff Vassilios Karakoidas
    meta_value = models.CharField('Image metadata value', max_length=500)
132 53827f6d Markos Gogoulos
    image = models.ForeignKey(Image)
133 53827f6d Markos Gogoulos
    
134 53827f6d Markos Gogoulos
    class Meta:
135 a0d4498a Vangelis Koukis
        verbose_name = u'Key-value pair of Image metadata.'
136 53827f6d Markos Gogoulos
    
137 53827f6d Markos Gogoulos
    def __unicode__(self):
138 53827f6d Markos Gogoulos
        return u'%s, %s for %s' % (self.meta_key, self.meta_value, self.image.name)
139 53827f6d Markos Gogoulos
140 53827f6d Markos Gogoulos
141 f51e7b50 Vassilios Karakoidas
class Limit(models.Model):
142 2d45374d Vassilios Karakoidas
    LIMITS = (
143 d174b105 Vassilios Karakoidas
        ('QUOTA_CREDIT', 'Maximum amount of credits per user'),
144 d174b105 Vassilios Karakoidas
        ('MIN_CREDITS', 'Minimum amount of credits per user'),
145 bf48028e Vassilios Karakoidas
        ('MONTHLY_RATE', 'Monthly credit issue rate')
146 2d45374d Vassilios Karakoidas
    )
147 d08a5f6f Vangelis Koukis
    user = models.ForeignKey(SynnefoUser)
148 13b3c5ff Vassilios Karakoidas
    name = models.CharField('Limit key name', choices=LIMITS, max_length=30, null=False)
149 13b3c5ff Vassilios Karakoidas
    value = models.IntegerField('Limit current value')
150 be7b8d37 Vassilios Karakoidas
    
151 46547e14 Faidon Liambotis
    class Meta:
152 dcfc6c2d Vangelis Koukis
        verbose_name = u'Enforced limit for user'
153 be7b8d37 Vassilios Karakoidas
    
154 46547e14 Faidon Liambotis
    def __unicode__(self):
155 452d2391 Vassilios Karakoidas
        return u'Limit %s for user %s: %d' % (self.value, self.user, self.value)
156 46547e14 Faidon Liambotis
157 e7164ebc Vassilios Karakoidas
158 e7164ebc Vassilios Karakoidas
class Flavor(models.Model):
159 13b3c5ff Vassilios Karakoidas
    cpu = models.IntegerField('Number of CPUs', default=0)
160 80da6543 Giorgos Verigakis
    ram = models.IntegerField('Size of RAM', default=0)             # Size in MiB
161 80da6543 Giorgos Verigakis
    disk = models.IntegerField('Size of Disk space', default=0)     # Size in GiB
162 be7b8d37 Vassilios Karakoidas
    
163 be7b8d37 Vassilios Karakoidas
    class Meta:
164 dcfc6c2d Vangelis Koukis
        verbose_name = u'Virtual machine flavor'
165 60bf38e1 Vangelis Koukis
        unique_together = ("cpu","ram","disk")
166 6c9a62b5 Vassilios Karakoidas
            
167 be7b8d37 Vassilios Karakoidas
    def _get_name(self):
168 f0f4edac Vassilios Karakoidas
        """Returns flavor name (generated)"""
169 d08a5f6f Vangelis Koukis
        return u'C%dR%dD%d' % (self.cpu, self.ram, self.disk)
170 452d2391 Vassilios Karakoidas
171 452d2391 Vassilios Karakoidas
    def _current_cost(self, active):
172 452d2391 Vassilios Karakoidas
        """Returns active/inactive cost value
173 452d2391 Vassilios Karakoidas

174 452d2391 Vassilios Karakoidas
        set active = True to get active cost and False for the inactive.
175 452d2391 Vassilios Karakoidas

176 452d2391 Vassilios Karakoidas
        """
177 d174b105 Vassilios Karakoidas
        fch_list = FlavorCost.objects.filter(flavor=self).order_by('-effective_from')
178 d174b105 Vassilios Karakoidas
        if len(fch_list) > 0:
179 452d2391 Vassilios Karakoidas
            if active:
180 452d2391 Vassilios Karakoidas
                return fch_list[0].cost_active
181 452d2391 Vassilios Karakoidas
            else:
182 452d2391 Vassilios Karakoidas
                return fch_list[0].cost_inactive
183 452d2391 Vassilios Karakoidas
184 d174b105 Vassilios Karakoidas
        return 0
185 452d2391 Vassilios Karakoidas
186 452d2391 Vassilios Karakoidas
    def _current_cost_active(self):
187 452d2391 Vassilios Karakoidas
        """Returns current active cost (property method)"""
188 452d2391 Vassilios Karakoidas
        return self._current_cost(True)
189 46547e14 Faidon Liambotis
190 d174b105 Vassilios Karakoidas
    def _current_cost_inactive(self):
191 452d2391 Vassilios Karakoidas
        """Returns current inactive cost (property method)"""
192 452d2391 Vassilios Karakoidas
        return self._current_cost(False)
193 05a90a5b Vassilios Karakoidas
194 be7b8d37 Vassilios Karakoidas
    name = property(_get_name)
195 d174b105 Vassilios Karakoidas
    current_cost_active = property(_current_cost_active)
196 d174b105 Vassilios Karakoidas
    current_cost_inactive = property(_current_cost_inactive)
197 00318048 Vassilios Karakoidas
198 46547e14 Faidon Liambotis
    def __unicode__(self):
199 46547e14 Faidon Liambotis
        return self.name
200 452d2391 Vassilios Karakoidas
201 46547e14 Faidon Liambotis
202 d174b105 Vassilios Karakoidas
class FlavorCost(models.Model):
203 13b3c5ff Vassilios Karakoidas
    cost_active = models.PositiveIntegerField('Active Cost')
204 13b3c5ff Vassilios Karakoidas
    cost_inactive = models.PositiveIntegerField('Inactive Cost')
205 452d2391 Vassilios Karakoidas
    effective_from = models.DateTimeField()
206 41b972e6 Vassilios Karakoidas
    flavor = models.ForeignKey(Flavor)
207 41b972e6 Vassilios Karakoidas
    
208 41b972e6 Vassilios Karakoidas
    class Meta:
209 41b972e6 Vassilios Karakoidas
        verbose_name = u'Pricing history for flavors'
210 41b972e6 Vassilios Karakoidas
    
211 41b972e6 Vassilios Karakoidas
    def __unicode__(self):
212 f533f224 Vangelis Koukis
        return u'Costs (up, down)=(%d, %d) for %s since %s' % \
213 f533f224 Vangelis Koukis
                (int(self.cost_active), int(self.cost_inactive),
214 f533f224 Vangelis Koukis
                 self.flavor.name, self.effective_from)
215 41b972e6 Vassilios Karakoidas
216 41b972e6 Vassilios Karakoidas
217 07f3219d Vassilios Karakoidas
class VirtualMachine(models.Model):
218 c92af313 Vangelis Koukis
    # The list of possible actions for a VM
219 d08a5f6f Vangelis Koukis
    ACTIONS = (
220 d08a5f6f Vangelis Koukis
       ('CREATE', 'Create VM'),
221 d08a5f6f Vangelis Koukis
       ('START', 'Start VM'),
222 d08a5f6f Vangelis Koukis
       ('STOP', 'Shutdown VM'),
223 d08a5f6f Vangelis Koukis
       ('SUSPEND', 'Admin Suspend VM'),
224 d08a5f6f Vangelis Koukis
       ('REBOOT', 'Reboot VM'),
225 d08a5f6f Vangelis Koukis
       ('DESTROY', 'Destroy VM')
226 d08a5f6f Vangelis Koukis
    )
227 c92af313 Vangelis Koukis
    # The internal operating state of a VM
228 d08a5f6f Vangelis Koukis
    OPER_STATES = (
229 d08a5f6f Vangelis Koukis
        ('BUILD', 'Queued for creation'),
230 d08a5f6f Vangelis Koukis
        ('ERROR', 'Creation failed'),
231 d08a5f6f Vangelis Koukis
        ('STOPPED', 'Stopped'),
232 d08a5f6f Vangelis Koukis
        ('STARTED', 'Started'),
233 d08a5f6f Vangelis Koukis
        ('DESTROYED', 'Destroyed')
234 d08a5f6f Vangelis Koukis
    )
235 c92af313 Vangelis Koukis
    # The list of possible operations on the backend
236 d08a5f6f Vangelis Koukis
    BACKEND_OPCODES = (
237 d08a5f6f Vangelis Koukis
        ('OP_INSTANCE_CREATE', 'Create Instance'),
238 d08a5f6f Vangelis Koukis
        ('OP_INSTANCE_REMOVE', 'Remove Instance'),
239 d08a5f6f Vangelis Koukis
        ('OP_INSTANCE_STARTUP', 'Startup Instance'),
240 d08a5f6f Vangelis Koukis
        ('OP_INSTANCE_SHUTDOWN', 'Shutdown Instance'),
241 26fef2b9 Vangelis Koukis
        ('OP_INSTANCE_REBOOT', 'Reboot Instance'),
242 26fef2b9 Vangelis Koukis
243 26fef2b9 Vangelis Koukis
        # These are listed here for completeness,
244 26fef2b9 Vangelis Koukis
        # and are ignored for the time being
245 26fef2b9 Vangelis Koukis
        ('OP_INSTANCE_SET_PARAMS', 'Set Instance Parameters'),
246 26fef2b9 Vangelis Koukis
        ('OP_INSTANCE_QUERY_DATA', 'Query Instance Data'),
247 d08a5f6f Vangelis Koukis
    )
248 c92af313 Vangelis Koukis
    # A backend job may be in one of the following possible states
249 d08a5f6f Vangelis Koukis
    BACKEND_STATUSES = (
250 d08a5f6f Vangelis Koukis
        ('queued', 'request queued'),
251 d08a5f6f Vangelis Koukis
        ('waiting', 'request waiting for locks'),
252 d08a5f6f Vangelis Koukis
        ('canceling', 'request being canceled'),
253 d08a5f6f Vangelis Koukis
        ('running', 'request running'),
254 d08a5f6f Vangelis Koukis
        ('canceled', 'request canceled'),
255 d08a5f6f Vangelis Koukis
        ('success', 'request completed successfully'),
256 d08a5f6f Vangelis Koukis
        ('error', 'request returned error')
257 d08a5f6f Vangelis Koukis
    )
258 d08a5f6f Vangelis Koukis
259 d08a5f6f Vangelis Koukis
    # The operating state of a VM,
260 d08a5f6f Vangelis Koukis
    # upon the successful completion of a backend operation.
261 d08a5f6f Vangelis Koukis
    OPER_STATE_FROM_OPCODE = {
262 d08a5f6f Vangelis Koukis
        'OP_INSTANCE_CREATE': 'STARTED',
263 d08a5f6f Vangelis Koukis
        'OP_INSTANCE_REMOVE': 'DESTROYED',
264 d08a5f6f Vangelis Koukis
        'OP_INSTANCE_STARTUP': 'STARTED',
265 d08a5f6f Vangelis Koukis
        'OP_INSTANCE_SHUTDOWN': 'STOPPED',
266 26fef2b9 Vangelis Koukis
        'OP_INSTANCE_REBOOT': 'STARTED',
267 26fef2b9 Vangelis Koukis
        'OP_INSTANCE_SET_PARAMS': None,
268 26fef2b9 Vangelis Koukis
        'OP_INSTANCE_QUERY_DATA': None
269 d08a5f6f Vangelis Koukis
    }
270 d08a5f6f Vangelis Koukis
271 c92af313 Vangelis Koukis
    # This dictionary contains the correspondence between
272 c92af313 Vangelis Koukis
    # internal operating states and Server States as defined
273 c92af313 Vangelis Koukis
    # by the Rackspace API.
274 d08a5f6f Vangelis Koukis
    RSAPI_STATE_FROM_OPER_STATE = {
275 d08a5f6f Vangelis Koukis
        "BUILD": "BUILD",
276 d08a5f6f Vangelis Koukis
        "ERROR": "ERROR",
277 d08a5f6f Vangelis Koukis
        "STOPPED": "STOPPED",
278 d08a5f6f Vangelis Koukis
        "STARTED": "ACTIVE",
279 d08a5f6f Vangelis Koukis
        "DESTROYED": "DELETED"
280 d08a5f6f Vangelis Koukis
    }
281 d08a5f6f Vangelis Koukis
282 4daac449 Vassilios Karakoidas
    name = models.CharField('Virtual Machine Name', max_length=255)
283 34a619ae Vangelis Koukis
    owner = models.ForeignKey(SynnefoUser)
284 d174b105 Vassilios Karakoidas
    created = models.DateTimeField(auto_now_add=True)
285 d174b105 Vassilios Karakoidas
    updated = models.DateTimeField(auto_now=True)
286 d174b105 Vassilios Karakoidas
    charged = models.DateTimeField(default=datetime.datetime.now())
287 b4808d2b Vassilios Karakoidas
    sourceimage = models.ForeignKey("Image", null=False) 
288 22571df6 Vassilios Karakoidas
    hostid = models.CharField(max_length=100)
289 46547e14 Faidon Liambotis
    flavor = models.ForeignKey(Flavor)
290 c750d1d6 Vangelis Koukis
    deleted = models.BooleanField('Deleted', default=False)
291 c750d1d6 Vangelis Koukis
    suspended = models.BooleanField('Administratively Suspended', default=False)
292 d08a5f6f Vangelis Koukis
293 52194743 Vangelis Koukis
    # VM State 
294 52194743 Vangelis Koukis
    # The following fields are volatile data, in the sense
295 52194743 Vangelis Koukis
    # that they need not be persistent in the DB, but rather
296 52194743 Vangelis Koukis
    # get generated at runtime by quering Ganeti and applying
297 52194743 Vangelis Koukis
    # updates received from Ganeti.
298 73b2b65e Vassilios Karakoidas
    
299 73b2b65e Vassilios Karakoidas
    # In the future they could be moved to a separate caching layer
300 73b2b65e Vassilios Karakoidas
    # and removed from the database.
301 73b2b65e Vassilios Karakoidas
    # [vkoukis] after discussion with [faidon].
302 dfd19c2d Vassilios Karakoidas
    action = models.CharField(choices=ACTIONS, max_length=30, null=True)
303 dfd19c2d Vassilios Karakoidas
    operstate = models.CharField(choices=OPER_STATES, max_length=30, null=True)
304 dfd19c2d Vassilios Karakoidas
    backendjobid = models.PositiveIntegerField(null=True)
305 f533f224 Vangelis Koukis
    backendopcode = models.CharField(choices=BACKEND_OPCODES, max_length=30,
306 f533f224 Vangelis Koukis
                                     null=True)
307 f533f224 Vangelis Koukis
    backendjobstatus = models.CharField(choices=BACKEND_STATUSES, max_length=30,
308 f533f224 Vangelis Koukis
                                        null=True)
309 dfd19c2d Vassilios Karakoidas
    backendlogmsg = models.TextField(null=True)
310 d08a5f6f Vangelis Koukis
311 d08a5f6f Vangelis Koukis
    # Error classes
312 d08a5f6f Vangelis Koukis
    class InvalidBackendIdError(Exception):
313 d08a5f6f Vangelis Koukis
         def __init__(self, value):
314 d08a5f6f Vangelis Koukis
            self.value = value
315 d08a5f6f Vangelis Koukis
         def __str__(self):
316 d08a5f6f Vangelis Koukis
            return repr(self.value)
317 d08a5f6f Vangelis Koukis
318 d08a5f6f Vangelis Koukis
    class InvalidBackendMsgError(Exception):
319 d08a5f6f Vangelis Koukis
         def __init__(self, opcode, status):
320 d08a5f6f Vangelis Koukis
            self.opcode = opcode
321 d08a5f6f Vangelis Koukis
            self.status = status
322 d08a5f6f Vangelis Koukis
         def __str__(self):
323 f533f224 Vangelis Koukis
            return repr("<opcode: %s, status: %s>" % (str(self.opcode),
324 f533f224 Vangelis Koukis
                                                      str(self.status)))
325 d08a5f6f Vangelis Koukis
326 d08a5f6f Vangelis Koukis
    class InvalidActionError(Exception):
327 d08a5f6f Vangelis Koukis
         def __init__(self, action):
328 c92af313 Vangelis Koukis
            self._action = action
329 d08a5f6f Vangelis Koukis
         def __str__(self):
330 78d9b6b7 Vangelis Koukis
            return repr(str(self._action))
331 5231a38a Giorgos Verigakis
    
332 5231a38a Giorgos Verigakis
    class DeletedError(Exception):
333 5231a38a Giorgos Verigakis
        pass
334 5231a38a Giorgos Verigakis
    
335 5231a38a Giorgos Verigakis
    class BuildingError(Exception):
336 5231a38a Giorgos Verigakis
        pass
337 5231a38a Giorgos Verigakis
    
338 3846dfd0 Vassilios Karakoidas
    def __init__(self, *args, **kw):
339 d08a5f6f Vangelis Koukis
        """Initialize state for just created VM instances."""
340 d08a5f6f Vangelis Koukis
        super(VirtualMachine, self).__init__(*args, **kw)
341 bc9c872b Vangelis Koukis
        # This gets called BEFORE an instance gets save()d for
342 bc9c872b Vangelis Koukis
        # the first time.
343 d08a5f6f Vangelis Koukis
        if not self.pk: 
344 dfd19c2d Vassilios Karakoidas
            self.action = None
345 dfd19c2d Vassilios Karakoidas
            self.backendjobid = None
346 dfd19c2d Vassilios Karakoidas
            self.backendjobstatus = None
347 dfd19c2d Vassilios Karakoidas
            self.backendopcode = None
348 dfd19c2d Vassilios Karakoidas
            self.backendlogmsg = None
349 dfd19c2d Vassilios Karakoidas
            self.operstate = 'BUILD'
350 d08a5f6f Vangelis Koukis
351 224b5e19 Markos Gogoulos
    def _get_backend_id(self):
352 224b5e19 Markos Gogoulos
        """Returns the backend id for this VM by prepending backend-prefix."""
353 76ba77c1 Vangelis Koukis
        if not self.id:
354 76ba77c1 Vangelis Koukis
            raise VirtualMachine.InvalidBackendIdError("self.id is None")
355 92c53da1 Vassilios Karakoidas
        return '%s%s' % (settings.BACKEND_PREFIX_ID, str(self.id))
356 5b32775a Vassilios Karakoidas
357 224b5e19 Markos Gogoulos
    backend_id = property(_get_backend_id)
358 05a90a5b Vassilios Karakoidas
359 d08a5f6f Vangelis Koukis
    class Meta:
360 d08a5f6f Vangelis Koukis
        verbose_name = u'Virtual machine instance'
361 d08a5f6f Vangelis Koukis
        get_latest_by = 'created'
362 d08a5f6f Vangelis Koukis
    
363 d08a5f6f Vangelis Koukis
    def __unicode__(self):
364 d08a5f6f Vangelis Koukis
        return self.name
365 d08a5f6f Vangelis Koukis
366 4ffb82dc Vassilios Karakoidas
367 a31ff6cb Markos Gogoulos
class VirtualMachineGroup(models.Model):
368 52194743 Vangelis Koukis
    """Groups of VMs for SynnefoUsers"""
369 a31ff6cb Markos Gogoulos
    name = models.CharField(max_length=255)
370 52194743 Vangelis Koukis
    created = models.DateTimeField('Time of creation', auto_now_add=True)
371 52194743 Vangelis Koukis
    updated = models.DateTimeField('Time of last update', auto_now=True)
372 6496c622 Vassilios Karakoidas
    owner = models.ForeignKey(SynnefoUser)
373 a31ff6cb Markos Gogoulos
    machines = models.ManyToManyField(VirtualMachine)
374 a31ff6cb Markos Gogoulos
375 a31ff6cb Markos Gogoulos
    class Meta:
376 a31ff6cb Markos Gogoulos
        verbose_name = u'Virtual Machine Group'
377 a31ff6cb Markos Gogoulos
        verbose_name_plural = 'Virtual Machine Groups'
378 a31ff6cb Markos Gogoulos
        ordering = ['name']
379 a31ff6cb Markos Gogoulos
    
380 a31ff6cb Markos Gogoulos
    def __unicode__(self):
381 a31ff6cb Markos Gogoulos
        return self.name
382 a31ff6cb Markos Gogoulos
383 3f53219b Vassilios Karakoidas
384 be7b8d37 Vassilios Karakoidas
class VirtualMachineMetadata(models.Model):
385 be7b8d37 Vassilios Karakoidas
    meta_key = models.CharField(max_length=50)
386 be7b8d37 Vassilios Karakoidas
    meta_value = models.CharField(max_length=500)
387 be7b8d37 Vassilios Karakoidas
    vm = models.ForeignKey(VirtualMachine)
388 be7b8d37 Vassilios Karakoidas
    
389 be7b8d37 Vassilios Karakoidas
    class Meta:
390 dcfc6c2d Vangelis Koukis
        verbose_name = u'Key-value pair of metadata for a VM.'
391 be7b8d37 Vassilios Karakoidas
    
392 be7b8d37 Vassilios Karakoidas
    def __unicode__(self):
393 53827f6d Markos Gogoulos
        return u'%s, %s for %s' % (self.meta_key, self.meta_value, self.vm.name)
394 be7b8d37 Vassilios Karakoidas
395 be7b8d37 Vassilios Karakoidas
396 d174b105 Vassilios Karakoidas
class Debit(models.Model):
397 d174b105 Vassilios Karakoidas
    when = models.DateTimeField()
398 d174b105 Vassilios Karakoidas
    user = models.ForeignKey(SynnefoUser)
399 46547e14 Faidon Liambotis
    vm = models.ForeignKey(VirtualMachine)
400 d174b105 Vassilios Karakoidas
    description = models.TextField()
401 be7b8d37 Vassilios Karakoidas
    
402 46547e14 Faidon Liambotis
    class Meta:
403 b90da243 Vassilios Karakoidas
        verbose_name = u'Accounting log'
404 be7b8d37 Vassilios Karakoidas
405 5b32775a Vassilios Karakoidas
    def __unicode__(self):
406 f533f224 Vangelis Koukis
        return u'%s - %s - %s - %s' % (self.user.id, self.vm.name,
407 f533f224 Vangelis Koukis
                                       str(self.when), self.description)
408 38684389 Markos Gogoulos
409 9071888e Constantinos Venetsanopoulos
410 9071888e Constantinos Venetsanopoulos
class Disk(models.Model):
411 9071888e Constantinos Venetsanopoulos
    name = models.CharField(max_length=255)
412 52194743 Vangelis Koukis
    created = models.DateTimeField('Time of creation', auto_now_add=True)
413 52194743 Vangelis Koukis
    updated = models.DateTimeField('Time of last update', auto_now=True)
414 9071888e Constantinos Venetsanopoulos
    size = models.PositiveIntegerField('Disk size in GBs')
415 9071888e Constantinos Venetsanopoulos
    vm = models.ForeignKey(VirtualMachine, blank=True, null=True)
416 9071888e Constantinos Venetsanopoulos
    owner = models.ForeignKey(SynnefoUser, blank=True, null=True)  
417 52194743 Vangelis Koukis
418 9071888e Constantinos Venetsanopoulos
    class Meta:
419 9071888e Constantinos Venetsanopoulos
        verbose_name = u'Disk instance'
420 9071888e Constantinos Venetsanopoulos
421 9071888e Constantinos Venetsanopoulos
    def __unicode__(self):
422 9071888e Constantinos Venetsanopoulos
        return self.name
423 0269afd6 Giorgos Verigakis
424 0269afd6 Giorgos Verigakis
425 0269afd6 Giorgos Verigakis
class Network(models.Model):
426 f533f224 Vangelis Koukis
    NETWORK_STATES = (
427 f533f224 Vangelis Koukis
        ('ACTIVE', 'Active'),
428 f533f224 Vangelis Koukis
        ('DELETED', 'Deleted')
429 f533f224 Vangelis Koukis
    )
430 f533f224 Vangelis Koukis
    
431 0269afd6 Giorgos Verigakis
    name = models.CharField(max_length=255)
432 0269afd6 Giorgos Verigakis
    created = models.DateTimeField(auto_now_add=True)
433 0269afd6 Giorgos Verigakis
    updated = models.DateTimeField(auto_now=True)
434 f533f224 Vangelis Koukis
    owner = models.ForeignKey(SynnefoUser, null=True)
435 f533f224 Vangelis Koukis
    state = models.CharField(choices=NETWORK_STATES, max_length=30)
436 f533f224 Vangelis Koukis
    public = models.BooleanField(default=False)
437 f533f224 Vangelis Koukis
    link = models.ForeignKey('NetworkLink', related_name='+')
438 f533f224 Vangelis Koukis
    machines = models.ManyToManyField(VirtualMachine,
439 f533f224 Vangelis Koukis
                                        through='NetworkInterface')
440 0269afd6 Giorgos Verigakis
    
441 0269afd6 Giorgos Verigakis
    def __unicode__(self):
442 0269afd6 Giorgos Verigakis
        return self.name
443 4f8b91cd Georgios Gousios
444 f533f224 Vangelis Koukis
445 4f8b91cd Georgios Gousios
class Invitations(models.Model):
446 4f8b91cd Georgios Gousios
    source = models.ForeignKey(SynnefoUser, related_name="source")
447 4f8b91cd Georgios Gousios
    target = models.ForeignKey(SynnefoUser, related_name="target")
448 4f8b91cd Georgios Gousios
    accepted = models.BooleanField('Is the invitation accepted?', default=False)
449 4f8b91cd Georgios Gousios
    created = models.DateTimeField(auto_now_add=True)
450 4f8b91cd Georgios Gousios
    updated = models.DateTimeField(auto_now=True)
451 9f8ad4c5 Georgios Gousios
    level = models.IntegerField('Invitation depth level', null=True)
452 4f8b91cd Georgios Gousios
453 4f8b91cd Georgios Gousios
    class Meta:
454 4f8b91cd Georgios Gousios
        verbose_name = u'Invitation'
455 4f8b91cd Georgios Gousios
456 4f8b91cd Georgios Gousios
    def __unicode__(self):
457 4f8b91cd Georgios Gousios
        return self.name
458 f533f224 Vangelis Koukis
459 f533f224 Vangelis Koukis
460 f533f224 Vangelis Koukis
class NetworkInterface(models.Model):
461 f533f224 Vangelis Koukis
    FIREWALL_PROFILES = (
462 f533f224 Vangelis Koukis
        ('ENABLED', 'Enabled'),
463 26563957 Giorgos Verigakis
        ('DISABLED', 'Disabled'),
464 26563957 Giorgos Verigakis
        ('PROTECTED', 'Protected')
465 f533f224 Vangelis Koukis
    )
466 f533f224 Vangelis Koukis
    
467 f533f224 Vangelis Koukis
    machine = models.ForeignKey(VirtualMachine, related_name='nics')
468 f533f224 Vangelis Koukis
    network = models.ForeignKey(Network, related_name='nics')
469 f533f224 Vangelis Koukis
    created = models.DateTimeField(auto_now_add=True)
470 f533f224 Vangelis Koukis
    updated = models.DateTimeField(auto_now=True)
471 f533f224 Vangelis Koukis
    index = models.IntegerField(null=True)
472 f533f224 Vangelis Koukis
    mac = models.CharField(max_length=17, null=True)
473 f533f224 Vangelis Koukis
    ipv4 = models.CharField(max_length=15, null=True)
474 f533f224 Vangelis Koukis
    ipv6 = models.CharField(max_length=100, null=True)
475 f533f224 Vangelis Koukis
    firewall_profile = models.CharField(choices=FIREWALL_PROFILES,
476 f533f224 Vangelis Koukis
                                        max_length=30, null=True)
477 2987cd8a Giorgos Verigakis
    
478 2987cd8a Giorgos Verigakis
    def __unicode__(self):
479 2987cd8a Giorgos Verigakis
        return '%s@%s' % (self.machine.name, self.network.name)
480 f533f224 Vangelis Koukis
481 f533f224 Vangelis Koukis
482 f533f224 Vangelis Koukis
class NetworkLink(models.Model):
483 f533f224 Vangelis Koukis
    network = models.ForeignKey(Network, null=True, related_name='+')
484 f533f224 Vangelis Koukis
    index = models.IntegerField()
485 f533f224 Vangelis Koukis
    name = models.CharField(max_length=255)
486 f533f224 Vangelis Koukis
    available = models.BooleanField(default=True)
487 2987cd8a Giorgos Verigakis
    
488 2987cd8a Giorgos Verigakis
    def __unicode__(self):
489 2987cd8a Giorgos Verigakis
        return self.name