1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """
16 Non-authenticated dumper
17 """
18
19 import os
20 try:
21
22 import xmlrpclib
23 except ImportError:
24
25 import xmlrpc.client as xmlrpclib
26 import gzip
27 import sys
28
29 from rhn.UserDictCase import UserDictCase
30 from spacewalk.common.usix import raise_with_tb
31 from spacewalk.common.rhnLog import log_debug, log_error
32 from spacewalk.common.rhnConfig import CFG
33 from spacewalk.server import rhnSQL, rhnLib
34 from spacewalk.server.rhnHandler import rhnHandler
35 from spacewalk.server.importlib.backendLib import localtime
36 from spacewalk.common.rhnException import rhnFault
37
38 from spacewalk.common.rhnTranslate import _
39
40 from spacewalk.satellite_tools.exporter import exportLib
41 from spacewalk.satellite_tools.disk_dumper import dumper
42
43
46
47
50
51
54
55
57
58
60 rhnHandler.__init__(self)
61 dumper.XML_Dumper.__init__(self)
62 self.headers_out = UserDictCase()
63 self._raw_stream = req
64 self._raw_stream.content_type = 'application/octet-stream'
65 self.compress_level = 0
66
67 self._headers_sent = 0
68 self._is_closed = 0
69 self._compressed_stream = None
70
71 self.functions = [
72 'arches',
73 'arches_extra',
74 'channel_families',
75 'channels',
76 'get_comps',
77 'get_modules',
78 'channel_packages_short',
79 'packages_short',
80 'packages',
81 'source_packages',
82 'errata',
83 'blacklist_obsoletes',
84 'product_names',
85 'get_rpm',
86 'kickstartable_trees',
87 'get_ks_file',
88 'orgs',
89 ]
90
91 self.system_id = None
92 self._channel_family_query_template = """
93 select cfm.channel_family_id, 0 quantity
94 from rhnChannelFamilyMembers cfm,
95 rhnChannel c, rhnChannelFamily cf
96 where cfm.channel_id = c.id
97 and c.label in (%s)
98 and cfm.channel_family_id = cf.id
99 and cf.label != 'rh-public'
100 and (cf.org_id in (%s)
101 or cf.org_id is null)
102 union
103 select id channel_family_id, NULL quantity
104 from rhnChannelFamily
105 where label = 'rh-public'
106 """
107 self._channel_family_query_public = """
108 select id channel_family_id, 0 quantity
109 from rhnChannelFamily
110 where org_id in (%s)
111 or org_id is null
112 """
113 self._channel_family_query = None
114
116 log_debug(4, "is_closed", self._is_closed)
117 if self._is_closed:
118 raise Exception("Trying to write to a closed connection")
119 if self._headers_sent:
120 return
121 self._headers_sent = 1
122 if self.compress_level:
123 self.headers_out['Content-Encoding'] = 'gzip'
124
125 if error:
126
127 self.compress_level = 0
128 self._raw_stream.content_type = 'text/xml'
129 for h, v in self.headers_out.items():
130 self._raw_stream.headers_out[h] = str(v)
131 self._raw_stream.send_http_header()
132
133 if self.compress_level and init_compressed_stream:
134 log_debug(4, "Compressing with factor %s" % self.compress_level)
135 self._compressed_stream = gzip.GzipFile(None, "wb",
136 self.compress_level, self._raw_stream)
137
138 - def send(self, data):
152
153 write = send
154
156 log_debug(2, "Closing")
157 if self._is_closed:
158 log_debug(3, "Already closed")
159 return
160
161 if self._compressed_stream:
162 log_debug(5, "Closing a compressed stream")
163 try:
164 self._compressed_stream.close()
165 except IOError:
166 e = sys.exc_info()[1]
167
168 log_error("Error closing the stream", str(e))
169
170 self._compressed_stream = None
171 self._is_closed = 1
172 log_debug(3, "Closed")
173
175 if not channel_labels:
176
177 self._channel_family_query = self._channel_family_query_public % self.exportable_orgs
178 return self
179
180 self._channel_family_query = self._channel_family_query_template % (
181 ', '.join(["'%s'" % x for x in channel_labels]),
182 self.exportable_orgs)
183 return self
184
193
195 channels = {}
196 for dummy, attributes, child_elements in channels_dom:
197 channel_label = attributes['label']
198 channels[channel_label] = channel_entry = {}
199
200 packages = attributes['packages'].split()
201 del attributes['packages']
202
203
204 prefix = "rhn-package-"
205 prefix_len = len(prefix)
206 packages = [int(x[prefix_len:]) for x in packages]
207
208 channel_entry['packages'] = packages
209
210 ks_trees = attributes['kickstartable-trees'].split()
211
212 channel_entry['ks_trees'] = ks_trees
213
214
215 attributes.clear()
216
217
218 maps = {
219 'source-packages': ('source_packages', 'rhn-source-package-'),
220 'rhn-channel-errata': ('errata', 'rhn-erratum-'),
221 }
222
223 for tag_name, dummy, celem in child_elements:
224 if tag_name not in maps:
225 continue
226 field, prefix = maps[tag_name]
227 prefix_len = len(prefix)
228
229
230 objects = []
231 for dummy, ceattr, dummy in celem:
232 obj_id = ceattr['id']
233 obj_id = int(obj_id[prefix_len:])
234 last_modified = localtime(ceattr['last-modified'])
235 objects.append((obj_id, last_modified))
236 channel_entry[field] = objects
237
238
239 del child_elements[:]
240
241 return channels
242
243 _cleanse_channels = staticmethod(_cleanse_channels)
244
245
261
274
279
280 - def _packages(self, packages, prefix, dump_class, sources=0):
283
286
290
293
296
299
302
305
309
310 - def channels(self, channel_labels, flags={}):
315
318
321
325
329
333
337
341
344
348
349 - def get_rpm(self, package, channel):
352
354 comps_query = """
355 select relative_filename
356 from rhnChannelComps
357 where channel_id = (
358 select id
359 from rhnChannel
360 where label = :channel_label
361 and comps_type_id = :ctype_id
362 )
363 order by id desc
364 """
365 channel_comps_sth = rhnSQL.prepare(comps_query)
366 channel_comps_sth.execute(channel_label=channel, ctype_id=comps_type_id)
367 row = channel_comps_sth.fetchone_dict()
368 if not row:
369 raise rhnFault(3015, "No comps/modules file for channel [%s]" % channel)
370 path = os.path.join(CFG.MOUNT_POINT, row['relative_filename'])
371 if not os.path.exists(path):
372 log_error("Missing comps/modules file [%s] for channel [%s]" % (path, channel))
373 raise rhnFault(3016, "Unable to retrieve comps/modules file for channel [%s]" % channel)
374 return self._send_stream(path)
375
377 log_debug(1, ks_label, relative_path)
378 h = rhnSQL.prepare("""
379 select base_path
380 from rhnKickstartableTree
381 where label = :ks_label
382 and org_id is null
383 """)
384 h.execute(ks_label=ks_label)
385 row = h.fetchone_dict()
386 if not row:
387 raise rhnFault(3003, "No such file %s in tree %s" %
388 (relative_path, ks_label))
389 path = os.path.join(CFG.MOUNT_POINT, row['base_path'], relative_path)
390 if not os.path.exists(path):
391 log_error("Missing file for satellite dumper: %s" % path)
392 raise rhnFault(3007, "Unable to retrieve file %s in tree %s" %
393 (relative_path, ks_label))
394 return self._send_stream(path)
395
396
397
398
408
409
410
411 _query_get_package_path_by_nvra = rhnSQL.Statement("""
412 select distinct
413 p.id, p.path
414 from rhnPackage p,
415 rhnChannelPackage cp,
416 rhnChannel c,
417 rhnPackageArch pa
418 where c.label = :channel
419 and cp.channel_id = c.id
420 and cp.package_id = p.id
421 and p.name_id = LOOKUP_PACKAGE_NAME(:name)
422 and p.evr_id = LOOKUP_EVR(:epoch, :version, :release)
423 and p.package_arch_id = pa.id
424 and pa.label = :arch
425 """)
426
428 log_debug(3, fileName, channel)
429 fileName = str(fileName)
430 n, e, v, r, a = rhnLib.parseRPMFilename(fileName)
431
432 h = rhnSQL.prepare(self._query_get_package_path_by_nvra)
433 h.execute(name=n, version=v, release=r, epoch=e, arch=a, channel=channel)
434 try:
435 return _get_path_from_cursor(h)
436 except InvalidPackageError:
437 log_debug(4, "Error", "Non-existent package requested", fileName)
438 raise_with_tb(rhnFault(17, _("Invalid RPM package %s requested") % fileName), sys.exc_info()[2])
439 except NullPathPackageError:
440 e = sys.exc_info()[1]
441 package_id = e[0]
442 log_error("Package path null for package id", package_id)
443 raise_with_tb(rhnFault(17, _("Invalid RPM package %s requested") % fileName), sys.exc_info()[2])
444 except MissingPackageError:
445 e = sys.exc_info()[1]
446 filePath = e[0]
447 log_error("Package not found", filePath)
448 raise_with_tb(rhnFault(17, _("Package not found")), sys.exc_info()[2])
449
450
452 try:
453 stream = open(path)
454 except IOError:
455 e = sys.exc_info()[1]
456 if e.errno == 2:
457 raise_with_tb(rhnFault(3007, "Missing file %s" % path), sys.exc_info()[2])
458
459 raise
460
461 stream.seek(0, 2)
462 file_size = stream.tell()
463 stream.seek(0, 0)
464 log_debug(3, "Package size", file_size)
465 self.headers_out['Content-Length'] = file_size
466 self.compress_level = 0
467 self._raw_stream.content_type = 'application/x-rpm'
468 self._send_headers()
469 self.send_rpm(stream)
470 return 0
471
486
489
491
492 s = xmlrpclib.dumps((data, ))
493
494 self.headers_out['Content-Length'] = len(s)
495 self._raw_stream.content_type = 'text/xml'
496 for h, v in self.headers_out.items():
497 self._raw_stream.headers_out[h] = str(v)
498 self._raw_stream.send_http_header()
499 self._raw_stream.write(s)
500 return 0
501
502
504
505
507 self._tag_stack = []
508 self._cdata = []
509 self._root = None
510
511 - def open_tag(self, tag_name, attributes=None):
517
518 - def data(self, astring):
519 self._cdata.append(astring)
520
527
528 - def empty_tag(self, tag_name, attributes=None):
533
534 - def _add_node(self, tag_name, attributes, cdata):
535 node = (tag_name, attributes, cdata)
536 if not self._tag_stack:
537
538 self._root = node
539 return self._root
540
541
542 parent = self._tag_stack[-1]
543
544 parent[2].append(node)
545 return parent
546
548 assert self._root is not None
549 return self._root
550
551
552
553
554
555
561
562
580
581 rpcClasses = {
582 'dump': NonAuthenticatedDumper,
583 }
584