1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import base64
20 import os
21 try:
22
23 import xmlrpclib
24 except ImportError:
25
26 import xmlrpc.client as xmlrpclib
27 import sys
28 import hashlib
29
30 from spacewalk.common.usix import raise_with_tb
31 from spacewalk.common import rhnFlags
32 from spacewalk.common.rhnLog import log_debug
33 from spacewalk.common.rhnConfig import CFG
34 from spacewalk.common.checksum import getStringChecksum
35 from spacewalk.common.rhnException import rhnFault, rhnException
36
37 from spacewalk.server import rhnSQL, rhnUser, rhnCapability
38 from spacewalk.server.rhnHandler import rhnHandler
39
40 from spacewalk.server.config_common.templated_document import ServerTemplatedDocument, var_interp_prep
41
42
43 import rhnSession
44
45
46
47
52
53
59
60
63
64
67
68
71
72
75
76
79
80
83
84
87
88
91
92
93
94
96
98 log_debug(3)
99 rhnHandler.__init__(self)
100 self.functions = {
101 'rhn_login': 'login',
102 'test_session': 'test_session',
103 'max_upload_fsize': 'max_upload_file_size',
104 }
105 self.org_id = None
106
107
109 if function not in self.functions:
110 return None
111
112
113 rhnFlags.set('compress_response', 1)
114 return getattr(self, self.functions[function])
115
116
119
120
132
142
143
145 return {
146 'delim_start': CFG.config_delim_start,
147 'delim_end': CFG.config_delim_end,
148 }
149
158
161
163 return str(file['config_file_type_id']) == '1'
164
166 return str(file['config_file_type_id']) == '3'
167
168 _query_current_selinux_lookup = rhnSQL.Statement("""
169 select ci.selinux_ctx from rhnConfigInfo ci, rhnConfigRevision cr, rhnConfigFile cf
170 where ci.id = cr.config_info_id
171 and cf.id = cr.config_file_id
172 and cf.config_file_name_id = lookup_config_filename(:path)
173 and cr.revision = (
174 select max(mcr.revision) from rhnConfigRevision mcr, rhnConfigFile mcf
175 where mcf.id = mcr.config_file_id
176 and mcf.config_file_name_id = cf.config_file_name_id
177 )
178 """)
179
251
252
253 - def push_file(self, config_channel_id, file):
254 try:
255 result = self._push_file(config_channel_id, file)
256 except ConfigFilePathIncomplete:
257 e = sys.exc_info()[1]
258 raise_with_tb(rhnFault(4015, "Full path of file '%s' must be specified" % e.file.get('path'),
259 explain=0), sys.exc_info()[2])
260
261 except ConfigFileExistsError:
262 e = sys.exc_info()[1]
263 raise_with_tb(rhnFault(4013, "File %s already uploaded" % e.file.get('path'),
264 explain=0), sys.exc_info()[2])
265 except ConfigFileVersionMismatchError:
266 e = sys.exc_info()[1]
267 raise_with_tb(rhnFault(4012, "File %s uploaded with a different "
268 "version" % e.file.get('path'), explain=0), sys.exc_info()[2])
269 except ConfigFileMissingDelimError:
270 e = sys.exc_info()[1]
271 raise_with_tb(rhnFault(4008, "Delimiter not specified for file %s" %
272 e.file.get('path'), explain=0), sys.exc_info()[2])
273 except ConfigFileMissingContentError:
274 e = sys.exc_info()[1]
275 raise_with_tb(rhnFault(4007, "No content sent for file %s" %
276 e.file.get('path'), explain=0), sys.exc_info()[2])
277 except ConfigFileExceedsQuota:
278 e = sys.exc_info()[1]
279 raise_with_tb(rhnFault(4014, "File size of %s exceeds free quota space" %
280 e.file.get('path'), explain=0), sys.exc_info()[2])
281 except ConfigFileTooLargeError:
282 e = sys.exc_info()[1]
283 raise_with_tb(rhnFault(4003, "File size of %s larger than %s bytes" %
284 (e.file.get('path'), self._get_maximum_file_size()),
285 explain=0), sys.exc_info()[2])
286
287 rhnSQL.commit()
288 return result
289
290 _query_content_lookup = rhnSQL.Statement("""
291 select cc.id, cv.checksum_type, cv.checksum, file_size, contents, is_binary, delim_start, delim_end
292 from rhnConfigContent cc, rhnChecksumView cv
293 where cv.checksum = :checksum
294 and cv.checksum_type = :checksum_type
295 and file_size = :file_size
296 and checksum_id = cv.id
297 """)
298
299 _query_insert_content = rhnSQL.Statement("""
300 insert into rhnConfigContent
301 (id, checksum_id, file_size, contents, is_binary, delim_start, delim_end)
302 values (:config_content_id, lookup_checksum(:checksum_type, :checksum),
303 :file_size, :contents, :is_binary, :delim_start, :delim_end)
304 """)
305
306 - def _push_contents(self, file):
307
308 checksum_type = 'sha256'
309
310 file['file_size'] = 0
311 file['is_binary'] = 'N'
312
313 file_path = file.get('path')
314 file_contents = file.get('file_contents') or ''
315
316 if 'enc64' in file and file_contents:
317 file_contents = base64.decodestring(file_contents)
318
319 if 'config_file_type_id' not in file:
320 log_debug(4, "Client does not support config directories, so set file_type_id to 1")
321 file['config_file_type_id'] = '1'
322
323 file['checksum_type'] = checksum_type
324 file['checksum'] = getStringChecksum(checksum_type, file_contents or '')
325
326 if file_contents:
327 file['file_size'] = len(file_contents)
328
329 if file['file_size'] > self._get_maximum_file_size():
330 raise ConfigFileTooLargeError(file_path, file['file_size'])
331
332
333
334
335
336 try:
337 file_contents.decode('UTF-8')
338 except UnicodeDecodeError:
339 file['is_binary'] = 'Y'
340
341 h = rhnSQL.prepare(self._query_content_lookup)
342 h.execute(**file)
343 row = h.fetchone_dict()
344
345 if row:
346 db_contents = rhnSQL.read_lob(row['contents']) or ''
347 if file_contents == db_contents:
348
349 file['config_content_id'] = row['id']
350 log_debug(5, "same content")
351 return
352
353
354 content_seq = rhnSQL.Sequence('rhn_confcontent_id_seq')
355 config_content_id = content_seq.next()
356 file['config_content_id'] = config_content_id
357 file['contents'] = file_contents
358
359 h = rhnSQL.prepare(self._query_insert_content,
360 blob_map={'contents': 'contents'})
361 h.execute(**file)
362
363 _query_lookup_symlink_config_info = rhnSQL.Statement("""
364 select lookup_config_info(null, null, null, :selinux_ctx, lookup_config_filename(:symlink)) id
365 from dual
366 """)
367
368 _query_lookup_non_symlink_config_info = rhnSQL.Statement("""
369 select lookup_config_info(:username, :groupname, :file_mode, :selinux_ctx, null) id
370 from dual
371 """)
372
373 _query_lookup_config_file = rhnSQL.Statement("""
374 select id
375 from rhnConfigFile
376 where config_channel_id = :config_channel_id
377 and config_file_name_id = lookup_config_filename(:path)
378 """)
379
410
411 _query_lookup_revision = rhnSQL.Statement("""
412 select id, revision, config_content_id, config_info_id,
413 config_file_type_id
414 from rhnConfigRevision
415 where config_file_id = :config_file_id
416 order by revision desc
417 """)
418
420
421 file['revision'] = 1
422 h = rhnSQL.prepare(self._query_lookup_revision)
423 h.execute(**file)
424 row = h.fetchone_dict()
425 if row:
426
427
428 fields = ['config_content_id', 'config_info_id', 'config_file_type_id']
429
430 if 'config_file_type_id' not in file:
431 log_debug(4, "Client does not support config directories, so set file_type_id to 1")
432 file['config_file_type_id'] = '1'
433
434 for f in fields:
435 if file.get(f) != row.get(f):
436 break
437 else:
438
439 file['config_revision_id'] = row['id']
440 self._update_revision(file)
441 self._update_config_file(file)
442 return
443
444
445
446
447 revision = row['revision'] + 1
448 file['revision'] = revision
449
450
451 self._insert_revision(file)
452
453 if self.user and hasattr(self.user, 'getid'):
454 self._add_author(file, self.user)
455 self._update_config_file(file)
456
457 _query_update_revision = rhnSQL.Statement("""
458 update rhnConfigRevision
459 set modified = current_timestamp
460 where id = :config_revision_id
461 """)
462
466
468 insert_call = rhnSQL.Function("rhn_config.insert_revision",
469 rhnSQL.types.NUMBER())
470 file['config_revision_id'] = insert_call(file['revision'],
471 file['config_file_id'],
472 file.get('config_content_id', None),
473 file['config_info_id'],
474 file['config_file_type_id'])
475
476 _query_update_revision_add_author = rhnSQL.Statement("""
477 update rhnConfigRevision
478 set changed_by_id = :user_id
479 where id = :rev_id
480 """)
481
485
486 _query_update_config_file = rhnSQL.Statement("""
487 update rhnConfigFile
488 set latest_config_revision_id = :config_revision_id,
489 state_id = :state_id
490 where config_channel_id = :config_channel_id
491 and config_file_name_id = lookup_config_filename(:path)
492 """)
493
497
504
506 return CFG.maximum_config_file_size
507
510
511
559