]> git.ipfire.org Git - people/jschlag/pbs.git/blame - src/buildservice/uploads.py
hub: Refactor main application
[people/jschlag/pbs.git] / src / buildservice / uploads.py
CommitLineData
9137135a
MT
1#!/usr/bin/python
2
f6e6ff79
MT
3from __future__ import division
4
5import datetime
9137135a
MT
6import hashlib
7import logging
8import os
f6e6ff79 9import shutil
9137135a
MT
10import uuid
11
f6e6ff79
MT
12import pakfire.packages
13
2c909128
MT
14from . import base
15from . import misc
16from . import packages
9137135a 17
2c909128 18from .constants import *
9137135a
MT
19
20class Uploads(base.Object):
21 def get_by_uuid(self, _uuid):
22 upload = self.db.get("SELECT id FROM uploads WHERE uuid = %s", _uuid)
23
24 return Upload(self.pakfire, upload.id)
25
9137135a 26 def get_all(self):
f6e6ff79 27 uploads = self.db.query("SELECT id FROM uploads ORDER BY time_started DESC")
9137135a
MT
28
29 return [Upload(self.pakfire, u.id) for u in uploads]
30
31 def cleanup(self):
32 for upload in self.get_all():
33 upload.cleanup()
34
35
36class Upload(base.Object):
37 def __init__(self, pakfire, id):
38 base.Object.__init__(self, pakfire)
39
40 self.id = id
41 self.data = self.db.get("SELECT * FROM uploads WHERE id = %s", self.id)
42
43 @classmethod
f6e6ff79
MT
44 def create(cls, pakfire, filename, size, hash, builder=None, user=None):
45 assert builder or user
9137135a 46
f6e6ff79
MT
47 id = pakfire.db.execute("INSERT INTO uploads(uuid, filename, size, hash) \
48 VALUES(%s, %s, %s, %s)", "%s" % uuid.uuid4(), filename, size, hash)
49
50 if builder:
51 pakfire.db.execute("UPDATE uploads SET builder_id = %s WHERE id = %s",
52 builder.id, id)
53
54 elif user:
55 pakfire.db.execute("UPDATE uploads SET user_id = %s WHERE id = %s",
56 user.id, id)
9137135a
MT
57
58 upload = cls(pakfire, id)
59
60 # Create space to where we save the data.
61 dirname = os.path.dirname(upload.path)
62 if not os.path.exists(dirname):
63 os.makedirs(dirname)
64
65 # Create empty file.
66 f = open(upload.path, "w")
67 f.close()
68
69 return upload
70
71 @property
72 def uuid(self):
73 return self.data.uuid
74
75 @property
76 def hash(self):
77 return self.data.hash
78
79 @property
80 def filename(self):
81 return self.data.filename
82
83 @property
84 def path(self):
85 return os.path.join(UPLOADS_DIR, self.uuid, self.filename)
86
f6e6ff79
MT
87 @property
88 def size(self):
89 return self.data.size
90
91 @property
92 def progress(self):
93 return self.data.progress / self.size
94
9137135a
MT
95 @property
96 def builder(self):
f6e6ff79
MT
97 if self.data.builder_id:
98 return self.pakfire.builders.get_by_id(self.data.builder_id)
99
100 @property
101 def user(self):
102 if self.data.user_id:
103 return self.pakfire.users.get_by_id(self.data.user_id)
9137135a
MT
104
105 def append(self, data):
f6e6ff79
MT
106 # Check if the filesize was exceeded.
107 size = os.path.getsize(self.path) + len(data)
108 if size > self.data.size:
109 raise Exception, "Given filesize was exceeded for upload %s" % self.uuid
110
9137135a
MT
111 logging.debug("Writing %s bytes to %s" % (len(data), self.path))
112
113 f = open(self.path, "ab")
114 f.write(data)
115 f.close()
116
f6e6ff79
MT
117 self.db.execute("UPDATE uploads SET progress = %s WHERE id = %s",
118 size, self.id)
119
9137135a 120 def validate(self):
f6e6ff79
MT
121 size = os.path.getsize(self.path)
122 if not size == self.data.size:
123 logging.error("Filesize is not okay: %s" % (self.uuid))
124 return False
125
9137135a
MT
126 # Calculate a hash to validate the upload.
127 hash = misc.calc_hash1(self.path)
128
f6e6ff79 129 if not self.hash == hash:
9137135a 130 logging.error("Hash did not match: %s != %s" % (self.hash, hash))
f6e6ff79
MT
131 return False
132
133 return True
9137135a 134
f6e6ff79
MT
135 def finished(self):
136 """
137 Update the status of the upload in the database to "finished".
138 """
139 # Check if the file was completely uploaded and the hash is correct.
140 # If not, the upload has failed.
141 if not self.validate():
142 return False
143
144 self.db.execute("UPDATE uploads SET finished = 'Y', time_finished = NOW() \
145 WHERE id = %s", self.id)
146
147 return True
9137135a
MT
148
149 def remove(self):
150 # Remove the uploaded data.
f6e6ff79
MT
151 path = os.path.dirname(self.path)
152 if os.path.exists(path):
153 shutil.rmtree(path, ignore_errors=True)
9137135a
MT
154
155 # Delete the upload from the database.
156 self.db.execute("DELETE FROM uploads WHERE id = %s", self.id)
157
f6e6ff79
MT
158 @property
159 def time_started(self):
160 return self.data.time_started
9137135a 161
f6e6ff79
MT
162 @property
163 def time_running(self):
9137135a
MT
164 # Get the seconds since we are running.
165 try:
f6e6ff79 166 time_running = datetime.datetime.utcnow() - self.time_started
9137135a
MT
167 time_running = time_running.total_seconds()
168 except:
169 time_running = 0
170
f6e6ff79
MT
171 return time_running
172
173 @property
174 def speed(self):
175 if not self.time_running:
176 return 0
177
178 return self.data.progress / self.time_running
179
180 def cleanup(self):
181 # Remove uploads that are older than 2 hours.
182 if self.time_running >= 3600 * 2:
9137135a 183 self.remove()