]> git.ipfire.org Git - pakfire.git/blame - python/pakfire/client/base.py
Merge branch 'master' of ssh://git.ipfire.org/pub/git/oddments/pakfire
[pakfire.git] / python / pakfire / client / base.py
CommitLineData
c62d93f1
MT
1#!/usr/bin/python
2
3from __future__ import division
4
5import os
6import socket
7import urlparse
8import xmlrpclib
9
10import pakfire.util
11import pakfire.packages as packages
12from pakfire.system import system
13
14# Local modules.
15import transport
16
17from pakfire.constants import *
38ba21f9 18from pakfire.i18n import _
c62d93f1
MT
19
20import logging
21log = logging.getLogger("pakfire.client")
22
23class PakfireClient(object):
24 type = None
25
26 def __init__(self, server, username, password):
27 self.url = self._join_url(server, username, password)
28
29 # Create a secure XMLRPC connection to the server.
30 self.conn = transport.Connection(self.url)
31
32 def _join_url(self, server, username, password):
33 """
34 Construct a right URL out of the given
35 server, username and password.
36
37 Basicly this just adds the credentials
38 to the URL.
39 """
40 assert self.type
41
42 # Parse the given URL.
43 url = urlparse.urlparse(server)
44 assert url.scheme in ("http", "https")
45
46 # Build new URL.
47 ret = "%s://" % url.scheme
48
49 # Add credentials if provided.
50 if username and password:
51 ret += "%s:%s@" % (username, password)
52
53 # Add host and path components.
54 ret += "%s/pakfirehub/%s" % (url.netloc, self.type)
55
56 return ret
57
58 ### Misc. actions
59
60 def noop(self):
61 """
62 No operation. Just to check if the connection is
63 working. Returns a random number.
64 """
65 return self.conn.noop()
66
67 def get_my_address(self):
68 """
69 Get my own address (as seen by the hub).
70 """
71 return self.conn.get_my_address()
72
73 def get_hub_status(self):
74 """
75 Get some status information about the hub.
76 """
77 return self.conn.get_hub_status()
78
79
80class BuildMixin(object):
81 ### Build actions
82
83 def build_create(self, filename, arches=None, distro=None):
84 """
85 Create a new build on the hub.
86 """
87
88 # Upload the source file to the server.
89 upload_id = self._upload_file(filename)
90
91 # Then create the build.
92 build = self.conn.build_create(upload_id, distro, arches)
93
94 print build
95
96 def _upload_file(self, filename):
97 # Get the hash of the file.
98 hash = pakfire.util.calc_hash1(filename)
99
100 # Get the size of the file.
101 size = os.path.getsize(filename)
102
103 # Get an upload ID from the server.
104 upload_id = self.conn.upload_create(os.path.basename(filename),
105 size, hash)
106
38ba21f9
MT
107 # Make a nice progressbar.
108 pb = pakfire.util.make_progress(os.path.basename(filename), size, speed=True, eta=True)
109
c62d93f1
MT
110 try:
111 # Calculate the number of chunks.
112 chunks = (size // CHUNK_SIZE) + 1
38ba21f9 113 transferred = 0
c62d93f1
MT
114
115 # Cut the file in pieces and upload them one after another.
116 with open(filename) as f:
117 chunk = 0
118 while True:
119 data = f.read(CHUNK_SIZE)
120 if not data:
121 break
122
123 chunk += 1
38ba21f9
MT
124 if pb:
125 transferred += len(data)
126 pb.update(transferred)
c62d93f1
MT
127
128 data = xmlrpclib.Binary(data)
129 self.conn.upload_chunk(upload_id, data)
130
131 # Tell the server, that we finished the upload.
132 ret = self.conn.upload_finished(upload_id)
133
134 except:
135 # If anything goes wrong, try to delete the upload and raise
136 # the exception.
137 self.conn.upload_remove(upload_id)
138
139 raise
140
38ba21f9
MT
141 finally:
142 if pb:
143 pb.finish()
144
c62d93f1
MT
145 # If the server sends false, something happened with the upload that
146 # could not be recovered.
38ba21f9 147 if not ret:
c62d93f1
MT
148 logging.error("Upload of %s was not successful." % filename)
149 raise Exception, "Upload failed."
150
151 return upload_id
152
153
154class PakfireUserClient(BuildMixin, PakfireClient):
155 type = "user"
156
157 def check_auth(self):
158 """
159 Check if the user was successfully authenticated.
160 """
161 return self.conn.check_auth()
162
163 def get_user_profile(self):
164 """
165 Get information about the user profile.
166 """
167 return self.conn.get_user_profile()
168
25a98632
MT
169 def get_builds(self, type=None, limit=10, offset=0):
170 return self.conn.get_builds(type=type, limit=limit, offset=offset)
171
172 def get_build(self, build_id):
173 return self.conn.get_build(build_id)
174
175 def get_builder(self, builder_id):
176 return self.conn.get_builder(builder_id)
177
178 def get_job(self, job_id):
179 return self.conn.get_job(job_id)
180
181 def get_latest_jobs(self):
182 return self.conn.get_latest_jobs()
183
184 def get_active_jobs(self):
185 return self.conn.get_active_jobs()
186
c62d93f1
MT
187
188class PakfireBuilderClient(BuildMixin, PakfireClient):
189 type = "builder"
190
191 def send_keepalive(self, overload=None):
192 """
193 Sends a little keepalive to the server and
194 updates the hardware information if the server
195 requests it.
196 """
197 log.debug("Sending keepalive to the hub.")
198
199 # Collect the current loadavg and send it to the hub.
200 loadavg = ", ".join(("%.2f" % round(l, 2) for l in os.getloadavg()))
201
202 needs_update = self.conn.send_keepalive(loadavg, overload)
203
204 if needs_update:
205 log.debug("The hub is requesting an update.")
206 self.send_update()
207
208 def send_update(self):
209 log.info("Sending host information update to hub...")
210
211 self.conn.send_update(
212 # Supported architectures.
213 system.supported_arches,
214
215 # CPU information.
216 system.cpu_model,
217 system.cpu_count,
218
219 # Amount of memory in bytes.
220 system.memory / 1024,
fc69babd
MT
221
222 # Send the currently running version of Pakfire.
223 PAKFIRE_VERSION,
c62d93f1 224 )