1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 import os
18 import sys
19 import fnmatch
20 import getpass
21
22
23
24
25
26
27
28 import inspect
29 from rhnpush import rhnpush_cache
30 from rhn.i18n import sstr
31 from up2date_client import rhnserver
32 from spacewalk.common import rhn_mpm
33 from spacewalk.common import rhn_rpm
34 from spacewalk.common.rhn_pkg import package_from_filename, get_package_header
35 from spacewalk.common.usix import raise_with_tb
36
37 if sys.version_info[0] == 3:
38 import xmlrpc.client as xmlrpclib
39 else:
40 import xmlrpclib
41
42 try:
43 from rhn import rpclib
44 Binary = rpclib.xmlrpclib.Binary
45 Output = rpclib.transports.Output
46 except ImportError:
47
48 rpclib = xmlrpclib
49 Binary = rpclib.Binary
50
51 import cgiwrap
52 Output = cgiwrap.Output
53
54
55 BUFFER_SIZE = 65536
56 HEADERS_PER_CALL = 25
63
66
67 - def __init__(self, faultCode=None, faultString="", faultExplanation=""):
68 Exception.__init__(self)
69 self.faultCode = faultCode
70 self.faultString = faultString
71 self.faultExplanation = faultExplanation
72
75
76 """Functionality for an uploading tool
77 """
78
79 - def __init__(self, options, files=None):
80 self.options = options
81 self.username = None
82 self.password = None
83 self.proxy = None
84 self.proxyUsername = None
85 self.proxyPassword = None
86 self.ca_chain = None
87 self.force = None
88 self.files = files or []
89 self.new_sat = None
90 self.url = None
91 self.channels = None
92 self.count = None
93 self.server = None
94 self.session = None
95 self.orgId = None
96 self.relativeDir = None
97 self.use_session = True
98 self.use_checksum_paths = False
99
100 - def warn(self, verbose, *args):
103
104 @staticmethod
105 - def die(errcode, *args):
109
113
119
121 self.proxyUsername = None
122 self.proxyPassword = None
123
125 self.ca_chain = self.options.ca_chain
126
132
135
155
161
162 setNoChannels = setChannels
163
166
172
174 self.relativeDir = None
175
183
185 if not self.options.exclude:
186 return self
187 for f in self.files[:]:
188 bf = os.path.basename(f)
189 for pattern in self.options.exclude:
190 if fnmatch.fnmatch(bf, pattern):
191 self.warn(1, "Ignoring %s" % f)
192 self.files.remove(f)
193 return self
194
196 self.warn(1, "Reading package names from stdin")
197 self.files = self.files + readStdin()
198
208
210 if self.use_session:
211 if self.use_checksum_paths:
212 return listChannelChecksumBySession(self.server,
213 self.session.getSessionString(), self.channels)
214
215 return listChannelBySession(self.server,
216 self.session.getSessionString(),
217 self.channels)
218
219 if self.use_checksum_paths:
220 return listChannelChecksum(self.server,
221 self.username, self.password,
222 self.channels)
223
224 return listChannel(self.server,
225 self.username, self.password,
226 self.channels)
227
246
263
265
266 localPackagesHash = {}
267 for filename in self.files:
268 nvrea = self._processFile(filename, nosig=1)['nvrea']
269 name = nvrea[0]
270 if name not in localPackagesHash:
271 localPackagesHash[name] = {nvrea: filename}
272 continue
273
274 same_names_hash = localPackagesHash[name]
275
276 if nvrea in same_names_hash:
277
278 continue
279 skip_rpm = 0
280 for local_nvrea in same_names_hash.keys():
281
282 ret = packageCompare(local_nvrea, nvrea,
283 is_mpm=0)
284 if ret == 0 and local_nvrea[4] == nvrea[4]:
285
286 skip_rpm = 1
287 break
288
289 if ret > 0:
290
291 skip_rpm = 1
292 break
293
294 if ret < 0:
295
296 del same_names_hash[local_nvrea]
297
298
299
300 if skip_rpm:
301
302 continue
303
304 same_names_hash[nvrea] = filename
305
306
307 pkglist = self._listChannel()
308
309 for p in pkglist:
310 name = p[0]
311 if name not in localPackagesHash:
312
313 continue
314 same_names_hash = localPackagesHash[name]
315 remote_nvrea = tuple(p[:5])
316 if remote_nvrea in same_names_hash:
317
318 del same_names_hash[remote_nvrea]
319 continue
320
321 for local_nvrea in list(same_names_hash.keys()):
322
323 ret = packageCompare(local_nvrea, remote_nvrea,
324 is_mpm=0)
325 if ret < 0:
326
327 del same_names_hash[local_nvrea]
328 continue
329 if ret == 0 and local_nvrea[4] == remote_nvrea[4]:
330
331 del same_names_hash[local_nvrea]
332 continue
333
334
335
336 l = []
337 for fhash in localPackagesHash.values():
338 for filename in fhash.values():
339 l.append(filename)
340 l.sort()
341 self.files = l
342
350
352 localPackagesHash = {}
353 for filename in self.files:
354 localPackagesHash[os.path.basename(filename)] = filename
355
356
357 pkglist = self._listMissingSourcePackages()
358
359 to_push = []
360 for pkg in pkglist:
361 pkg_name, _pkg_channel = pkg[:2]
362 if pkg_name not in localPackagesHash:
363
364 continue
365 to_push.append(localPackagesHash[pkg_name])
366
367 to_push.sort()
368 self.files = to_push
369 return self.files
370
372
373 for p in self.files:
374 print(p)
375
378
386
394
396
397 self.setForce()
398
399 self.setRelativeDir()
400
401 self.setCount()
402
403 self.setOrg()
404
405 self.setURL()
406
407 self.setNoChannels()
408
409
410 self.setServer()
411
412 self.authenticate()
413
414 source = self.options.source
415 file_list = self._get_files()
416
417 while file_list:
418 chunk = file_list[:self.count]
419 del file_list[:self.count]
420 uploadedPackages, headersList = self._processBatch(chunk,
421 relativeDir=self.relativeDir, source=self.options.source,
422 verbose=self.options.verbose, nosig=self.options.nosig)
423
424 if not headersList:
425
426 continue
427
428
429 info = {'packages': headersList}
430 if self.orgId > 0 or self.orgId == '':
431 info['orgId'] = self.orgId
432
433 if self.force:
434 info['force'] = self.force
435
436 if self.channels:
437 info['channels'] = self.channels
438
439
440 if self.options.verbose:
441 ReportError("Uploading batch:")
442 for p in list(uploadedPackages.values())[0]:
443 ReportError("\t\t%s" % p)
444
445 if source:
446 ret = self._uploadSourcePackageInfo(info)
447 else:
448 ret = self._uploadPackageInfo(info)
449
450 if ret is None:
451 self.die(-1, "Upload attempt failed")
452
453
454 alreadyUploaded, newPackages = ret
455 pkglists = (alreadyUploaded, newPackages)
456
457 for idx, item in enumerate(pkglists):
458 for p in item:
459 key = tuple(p[:5])
460 if key not in uploadedPackages:
461
462 self.warn(1, "XXX XXX %s" % str(p))
463 filename, checksum = uploadedPackages[key]
464
465 if self.options.verbose:
466 if idx == 0:
467 pattern = "Already uploaded: %s"
468 else:
469 pattern = "Uploaded: %s"
470 print(pattern % filename)
471
472
473 try:
474 self.processPackage(p, filename, checksum)
475 except TypeError:
476 self.processPackage(p, filename)
477
480
483
491
501
516
517 @staticmethod
518 - def _processFile(filename, relativeDir=None, source=None, nosig=None):
519 """ Processes a file
520 Returns a hash containing:
521 header
522 packageSize
523 checksum
524 relativePath
525 nvrea
526 """
527
528
529 if not os.access(filename, os.R_OK):
530 raise UploadError("Could not stat the file %s" % filename)
531 if not os.path.isfile(filename):
532 raise UploadError("%s is not a file" % filename)
533
534
535 size = os.path.getsize(filename)
536
537 try:
538 a_pkg = package_from_filename(filename)
539 a_pkg.read_header()
540 a_pkg.payload_checksum()
541 assert a_pkg.header
542 except:
543 raise_with_tb(UploadError("%s is not a valid package" % filename), sys.exc_info()[2])
544
545 if nosig is None and not a_pkg.header.is_signed():
546 raise UploadError("ERROR: %s: unsigned rpm (use --nosig to force)"
547 % filename)
548
549
550 lh = []
551 for k in ['name', 'version', 'release', 'epoch']:
552 if k == 'epoch' and not a_pkg.header[k]:
553
554 lh.append(sstr(""))
555 else:
556 lh.append(sstr(a_pkg.header[k]))
557
558 if source:
559 lh.append('src')
560 else:
561 lh.append(sstr(a_pkg.header['arch']))
562
563
564 info = {'header': Binary(a_pkg.header.unload()),
565 'checksum_type': a_pkg.checksum_type,
566 'checksum': a_pkg.checksum,
567 'packageSize': size,
568 'header_start': a_pkg.header_start,
569 'header_end': a_pkg.header_end}
570 if relativeDir:
571
572 info["relativePath"] = "%s/%s" % (relativeDir,
573 os.path.basename(filename))
574 info['nvrea'] = tuple(lh)
575 return info
576
577 - def _processBatch(self, batch, relativeDir, source, verbose, nosig=None):
594
597
598 l = []
599 while 1:
600 line = sys.stdin.readline()
601 if not line:
602 break
603 l.append(line.strip())
604 return l
605
608
609
610 if cmdlineUsername and cmdlinePassword:
611 return cmdlineUsername, cmdlinePassword
612
613 username = cmdlineUsername
614 password = cmdlinePassword
615
616
617 tty = open("/dev/tty", "w")
618 tty.write("Username: ")
619 tty.close()
620 tty = open("/dev/tty", "r")
621
622 while not username:
623 try:
624 username = tty.readline()
625 except KeyboardInterrupt:
626 tty.write("\n")
627 sys.exit(0)
628 if username is None:
629
630 tty.write("\n")
631 sys.exit(0)
632 username = username.strip()
633 if username:
634 break
635
636
637 while not password:
638 try:
639 password = getpass.getpass("Password: ")
640 except KeyboardInterrupt:
641 tty.write("\n")
642 sys.exit(0)
643 tty.close()
644 return username, password
645
658
659
660 -def call(function, *params, **kwargs):
661
662 try:
663 ret = function(*params)
664 except xmlrpclib.Fault:
665 e = sys.exc_info()[1]
666 x = parseXMLRPCfault(e)
667 if x.faultString:
668 print(x.faultString)
669 if x.faultExplanation:
670 print(x.faultExplanation)
671 sys.exit(-1)
672 except xmlrpclib.ProtocolError:
673 e = sys.exc_info()[1]
674 if kwargs.get('raise_protocol_error'):
675 raise
676 print(e.errmsg)
677 sys.exit(-1)
678
679 return ret
680
683 if not isinstance(fault, xmlrpclib.Fault):
684 return None
685 faultCode = fault.faultCode
686 if faultCode and isinstance(faultCode, type(1)):
687 faultCode = -faultCode
688 return ServerFault(faultCode, "", fault.faultString)
689
690
691
692
693 -def listChannel(server, username, password, channels):
695
700
704
709
713
717
721
725
729
733
737
743
747
748
749 -def getServer(uri, proxy=None, username=None, password=None, ca_chain=None):
754
766
781
802
817
820 sys.stderr.write(' '.join(map(str, args)) + "\n")
821