Statistics
| Branch: | Tag: | Revision:

root / db / models.py @ d41d6a00

History | View | Annotate | Download (17.5 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 420f2c20 Georgios Gousios
    type = models.CharField('Current Image State', choices=ACCOUNT_TYPE, max_length=30)
57 52194743 Vangelis Koukis
    created = models.DateTimeField('Time of creation', auto_now_add=True)
58 52194743 Vangelis Koukis
    updated = models.DateTimeField('Time of last update', auto_now=True)
59 33e00f02 Georgios Gousios
    max_invitations = models.IntegerField('Max number of invitations',
60 33e00f02 Georgios Gousios
                                          null=True)
61 92c53da1 Vassilios Karakoidas
62 be7b8d37 Vassilios Karakoidas
    class Meta:
63 d08a5f6f Vangelis Koukis
        verbose_name = u'Synnefo User'
64 420f2c20 Georgios Gousios
65 46547e14 Faidon Liambotis
    def __unicode__(self):
66 ef39e7ee Georgios Gousios
        return self.name
67 07f3219d Vassilios Karakoidas
68 1583f11a Vassilios Karakoidas
    def get_limit(self, limit_name):
69 1583f11a Vassilios Karakoidas
        """Returns the limit value for the specified limit"""
70 6bffabbd Vassilios Karakoidas
        limit_objs = Limit.objects.filter(name=limit_name, user=self)
71 1583f11a Vassilios Karakoidas
        if len(limit_objs) == 1:
72 1583f11a Vassilios Karakoidas
            return limit_objs[0].value
73 1583f11a Vassilios Karakoidas
        
74 1583f11a Vassilios Karakoidas
        return 0
75 bf48028e Vassilios Karakoidas
        
76 bf48028e Vassilios Karakoidas
    def _get_credit_quota(self):
77 bf48028e Vassilios Karakoidas
        """Internal getter function for credit quota"""
78 bf48028e Vassilios Karakoidas
        return self.get_limit('QUOTA_CREDIT')
79 bf48028e Vassilios Karakoidas
        
80 bf48028e Vassilios Karakoidas
    credit_quota = property(_get_credit_quota)
81 bf48028e Vassilios Karakoidas
    
82 bf48028e Vassilios Karakoidas
    def _get_monthly_rate(self):
83 bf48028e Vassilios Karakoidas
        """Internal getter function for monthly credit issue rate"""
84 bf48028e Vassilios Karakoidas
        return self.get_limit('MONTHLY_RATE')
85 bf48028e Vassilios Karakoidas
        
86 bf48028e Vassilios Karakoidas
    monthly_rate = property(_get_monthly_rate)
87 bf48028e Vassilios Karakoidas
    
88 d174b105 Vassilios Karakoidas
    def _get_min_credits(self):
89 bf48028e Vassilios Karakoidas
        """Internal getter function for maximum number of violations"""
90 d174b105 Vassilios Karakoidas
        return self.get_limit('MIN_CREDITS')
91 bf48028e Vassilios Karakoidas
        
92 d174b105 Vassilios Karakoidas
    min_credits = property(_get_min_credits)
93 b1699441 Vassilios Karakoidas
94 0b5a51f7 Vassilios Karakoidas
95 6496c622 Vassilios Karakoidas
class Image(models.Model):
96 6496c622 Vassilios Karakoidas
    # This is WIP, FIXME
97 6496c622 Vassilios Karakoidas
    IMAGE_STATES = (
98 b4808d2b Vassilios Karakoidas
        ('ACTIVE', 'Active'),
99 b4808d2b Vassilios Karakoidas
        ('SAVING', 'Saving'),
100 b4808d2b Vassilios Karakoidas
        ('DELETED', 'Deleted')
101 6496c622 Vassilios Karakoidas
    )
102 6496c622 Vassilios Karakoidas
103 b7d29d41 Constantinos Venetsanopoulos
    # The list of supported Image formats
104 b7d29d41 Constantinos Venetsanopoulos
    FORMATS = (
105 27ccb60f Constantinos Venetsanopoulos
        ('dump', 'ext3 dump'),
106 27ccb60f Constantinos Venetsanopoulos
        ('lvm', 'lvm snapshot'),
107 27ccb60f Constantinos Venetsanopoulos
        ('ntfsclone', 'Windows Image produced by ntfsclone')
108 b7d29d41 Constantinos Venetsanopoulos
    )
109 b7d29d41 Constantinos Venetsanopoulos
110 13b3c5ff Vassilios Karakoidas
    name = models.CharField('Image name', max_length=255)
111 a191bd4d Giorgos Verigakis
    state = models.CharField('Current Image State', choices=IMAGE_STATES,
112 a191bd4d Giorgos Verigakis
                                max_length=30)
113 a0d4498a Vangelis Koukis
    owner = models.ForeignKey(SynnefoUser, blank=True, null=True)
114 52194743 Vangelis Koukis
    created = models.DateTimeField('Time of creation', auto_now_add=True)
115 52194743 Vangelis Koukis
    updated = models.DateTimeField('Time of last update', auto_now=True)
116 b4808d2b Vassilios Karakoidas
    sourcevm = models.ForeignKey("VirtualMachine", null=True)
117 b7d29d41 Constantinos Venetsanopoulos
    backend_id = models.CharField(max_length=50, default='debian_base')
118 b7d29d41 Constantinos Venetsanopoulos
    format = models.CharField(choices=FORMATS, max_length=30, default='dump')
119 75768d0e Giorgos Verigakis
    public = models.BooleanField(default=False)
120 6496c622 Vassilios Karakoidas
121 6496c622 Vassilios Karakoidas
    class Meta:
122 6496c622 Vassilios Karakoidas
        verbose_name = u'Image'
123 6496c622 Vassilios Karakoidas
124 6496c622 Vassilios Karakoidas
    def __unicode__(self):
125 452d2391 Vassilios Karakoidas
        return u'%s' % ( self.name, )
126 6496c622 Vassilios Karakoidas
127 53827f6d Markos Gogoulos
128 53827f6d Markos Gogoulos
class ImageMetadata(models.Model):
129 13b3c5ff Vassilios Karakoidas
    meta_key = models.CharField('Image metadata key name', max_length=50)
130 13b3c5ff Vassilios Karakoidas
    meta_value = models.CharField('Image metadata value', max_length=500)
131 53827f6d Markos Gogoulos
    image = models.ForeignKey(Image)
132 53827f6d Markos Gogoulos
    
133 53827f6d Markos Gogoulos
    class Meta:
134 a0d4498a Vangelis Koukis
        verbose_name = u'Key-value pair of Image metadata.'
135 53827f6d Markos Gogoulos
    
136 53827f6d Markos Gogoulos
    def __unicode__(self):
137 53827f6d Markos Gogoulos
        return u'%s, %s for %s' % (self.meta_key, self.meta_value, self.image.name)
138 53827f6d Markos Gogoulos
139 53827f6d Markos Gogoulos
140 f51e7b50 Vassilios Karakoidas
class Limit(models.Model):
141 2d45374d Vassilios Karakoidas
    LIMITS = (
142 d174b105 Vassilios Karakoidas
        ('QUOTA_CREDIT', 'Maximum amount of credits per user'),
143 d174b105 Vassilios Karakoidas
        ('MIN_CREDITS', 'Minimum amount of credits per user'),
144 bf48028e Vassilios Karakoidas
        ('MONTHLY_RATE', 'Monthly credit issue rate')
145 2d45374d Vassilios Karakoidas
    )
146 d08a5f6f Vangelis Koukis
    user = models.ForeignKey(SynnefoUser)
147 13b3c5ff Vassilios Karakoidas
    name = models.CharField('Limit key name', choices=LIMITS, max_length=30, null=False)
148 13b3c5ff Vassilios Karakoidas
    value = models.IntegerField('Limit current value')
149 be7b8d37 Vassilios Karakoidas
    
150 46547e14 Faidon Liambotis
    class Meta:
151 dcfc6c2d Vangelis Koukis
        verbose_name = u'Enforced limit for user'
152 be7b8d37 Vassilios Karakoidas
    
153 46547e14 Faidon Liambotis
    def __unicode__(self):
154 452d2391 Vassilios Karakoidas
        return u'Limit %s for user %s: %d' % (self.value, self.user, self.value)
155 46547e14 Faidon Liambotis
156 e7164ebc Vassilios Karakoidas
157 e7164ebc Vassilios Karakoidas
class Flavor(models.Model):
158 13b3c5ff Vassilios Karakoidas
    cpu = models.IntegerField('Number of CPUs', default=0)
159 80da6543 Giorgos Verigakis
    ram = models.IntegerField('Size of RAM', default=0)             # Size in MiB
160 80da6543 Giorgos Verigakis
    disk = models.IntegerField('Size of Disk space', default=0)     # Size in GiB
161 be7b8d37 Vassilios Karakoidas
    
162 be7b8d37 Vassilios Karakoidas
    class Meta:
163 dcfc6c2d Vangelis Koukis
        verbose_name = u'Virtual machine flavor'
164 60bf38e1 Vangelis Koukis
        unique_together = ("cpu","ram","disk")
165 6c9a62b5 Vassilios Karakoidas
            
166 be7b8d37 Vassilios Karakoidas
    def _get_name(self):
167 f0f4edac Vassilios Karakoidas
        """Returns flavor name (generated)"""
168 d08a5f6f Vangelis Koukis
        return u'C%dR%dD%d' % (self.cpu, self.ram, self.disk)
169 452d2391 Vassilios Karakoidas
170 452d2391 Vassilios Karakoidas
    def _current_cost(self, active):
171 452d2391 Vassilios Karakoidas
        """Returns active/inactive cost value
172 452d2391 Vassilios Karakoidas

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

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