diff options
Diffstat (limited to 'scripts/lib/mic/utils/rpmmisc.py')
| -rw-r--r-- | scripts/lib/mic/utils/rpmmisc.py | 600 |
1 files changed, 600 insertions, 0 deletions
diff --git a/scripts/lib/mic/utils/rpmmisc.py b/scripts/lib/mic/utils/rpmmisc.py new file mode 100644 index 0000000000..af15763e18 --- /dev/null +++ b/scripts/lib/mic/utils/rpmmisc.py | |||
| @@ -0,0 +1,600 @@ | |||
| 1 | #!/usr/bin/python -tt | ||
| 2 | # | ||
| 3 | # Copyright (c) 2008, 2009, 2010, 2011 Intel, Inc. | ||
| 4 | # | ||
| 5 | # This program is free software; you can redistribute it and/or modify it | ||
| 6 | # under the terms of the GNU General Public License as published by the Free | ||
| 7 | # Software Foundation; version 2 of the License | ||
| 8 | # | ||
| 9 | # This program is distributed in the hope that it will be useful, but | ||
| 10 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
| 11 | # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
| 12 | # for more details. | ||
| 13 | # | ||
| 14 | # You should have received a copy of the GNU General Public License along | ||
| 15 | # with this program; if not, write to the Free Software Foundation, Inc., 59 | ||
| 16 | # Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 17 | |||
| 18 | import os | ||
| 19 | import sys | ||
| 20 | import re | ||
| 21 | import rpm | ||
| 22 | |||
| 23 | from mic import msger | ||
| 24 | from mic.utils.errors import CreatorError | ||
| 25 | from mic.utils.proxy import get_proxy_for | ||
| 26 | from mic.utils import runner | ||
| 27 | |||
| 28 | |||
| 29 | class RPMInstallCallback: | ||
| 30 | """ Command line callback class for callbacks from the RPM library. | ||
| 31 | """ | ||
| 32 | |||
| 33 | def __init__(self, ts, output=1): | ||
| 34 | self.output = output | ||
| 35 | self.callbackfilehandles = {} | ||
| 36 | self.total_actions = 0 | ||
| 37 | self.total_installed = 0 | ||
| 38 | self.installed_pkg_names = [] | ||
| 39 | self.total_removed = 0 | ||
| 40 | self.mark = "+" | ||
| 41 | self.marks = 40 | ||
| 42 | self.lastmsg = None | ||
| 43 | self.tsInfo = None # this needs to be set for anything else to work | ||
| 44 | self.ts = ts | ||
| 45 | self.filelog = False | ||
| 46 | self.logString = [] | ||
| 47 | self.headmsg = "Installing" | ||
| 48 | |||
| 49 | def _dopkgtup(self, hdr): | ||
| 50 | tmpepoch = hdr['epoch'] | ||
| 51 | if tmpepoch is None: epoch = '0' | ||
| 52 | else: epoch = str(tmpepoch) | ||
| 53 | |||
| 54 | return (hdr['name'], hdr['arch'], epoch, hdr['version'], hdr['release']) | ||
| 55 | |||
| 56 | def _makeHandle(self, hdr): | ||
| 57 | handle = '%s:%s.%s-%s-%s' % (hdr['epoch'], hdr['name'], hdr['version'], | ||
| 58 | hdr['release'], hdr['arch']) | ||
| 59 | |||
| 60 | return handle | ||
| 61 | |||
| 62 | def _localprint(self, msg): | ||
| 63 | if self.output: | ||
| 64 | msger.info(msg) | ||
| 65 | |||
| 66 | def _makefmt(self, percent, progress = True): | ||
| 67 | l = len(str(self.total_actions)) | ||
| 68 | size = "%s.%s" % (l, l) | ||
| 69 | fmt_done = "[%" + size + "s/%" + size + "s]" | ||
| 70 | done = fmt_done % (self.total_installed + self.total_removed, | ||
| 71 | self.total_actions) | ||
| 72 | marks = self.marks - (2 * l) | ||
| 73 | width = "%s.%s" % (marks, marks) | ||
| 74 | fmt_bar = "%-" + width + "s" | ||
| 75 | if progress: | ||
| 76 | bar = fmt_bar % (self.mark * int(marks * (percent / 100.0)), ) | ||
| 77 | fmt = "\r %-10.10s: %-20.20s " + bar + " " + done | ||
| 78 | else: | ||
| 79 | bar = fmt_bar % (self.mark * marks, ) | ||
| 80 | fmt = " %-10.10s: %-20.20s " + bar + " " + done | ||
| 81 | return fmt | ||
| 82 | |||
| 83 | def _logPkgString(self, hdr): | ||
| 84 | """return nice representation of the package for the log""" | ||
| 85 | (n,a,e,v,r) = self._dopkgtup(hdr) | ||
| 86 | if e == '0': | ||
| 87 | pkg = '%s.%s %s-%s' % (n, a, v, r) | ||
| 88 | else: | ||
| 89 | pkg = '%s.%s %s:%s-%s' % (n, a, e, v, r) | ||
| 90 | |||
| 91 | return pkg | ||
| 92 | |||
| 93 | def callback(self, what, bytes, total, h, user): | ||
| 94 | if what == rpm.RPMCALLBACK_TRANS_START: | ||
| 95 | if bytes == 6: | ||
| 96 | self.total_actions = total | ||
| 97 | |||
| 98 | elif what == rpm.RPMCALLBACK_TRANS_PROGRESS: | ||
| 99 | pass | ||
| 100 | |||
| 101 | elif what == rpm.RPMCALLBACK_TRANS_STOP: | ||
| 102 | pass | ||
| 103 | |||
| 104 | elif what == rpm.RPMCALLBACK_INST_OPEN_FILE: | ||
| 105 | self.lastmsg = None | ||
| 106 | hdr = None | ||
| 107 | if h is not None: | ||
| 108 | try: | ||
| 109 | hdr, rpmloc = h | ||
| 110 | except: | ||
| 111 | rpmloc = h | ||
| 112 | hdr = readRpmHeader(self.ts, h) | ||
| 113 | |||
| 114 | handle = self._makeHandle(hdr) | ||
| 115 | fd = os.open(rpmloc, os.O_RDONLY) | ||
| 116 | self.callbackfilehandles[handle]=fd | ||
| 117 | if hdr['name'] not in self.installed_pkg_names: | ||
| 118 | self.installed_pkg_names.append(hdr['name']) | ||
| 119 | self.total_installed += 1 | ||
| 120 | return fd | ||
| 121 | else: | ||
| 122 | self._localprint("No header - huh?") | ||
| 123 | |||
| 124 | elif what == rpm.RPMCALLBACK_INST_CLOSE_FILE: | ||
| 125 | hdr = None | ||
| 126 | if h is not None: | ||
| 127 | try: | ||
| 128 | hdr, rpmloc = h | ||
| 129 | except: | ||
| 130 | rpmloc = h | ||
| 131 | hdr = readRpmHeader(self.ts, h) | ||
| 132 | |||
| 133 | handle = self._makeHandle(hdr) | ||
| 134 | os.close(self.callbackfilehandles[handle]) | ||
| 135 | fd = 0 | ||
| 136 | |||
| 137 | # log stuff | ||
| 138 | #pkgtup = self._dopkgtup(hdr) | ||
| 139 | self.logString.append(self._logPkgString(hdr)) | ||
| 140 | |||
| 141 | elif what == rpm.RPMCALLBACK_INST_PROGRESS: | ||
| 142 | if h is not None: | ||
| 143 | percent = (self.total_installed*100L)/self.total_actions | ||
| 144 | if total > 0: | ||
| 145 | try: | ||
| 146 | hdr, rpmloc = h | ||
| 147 | except: | ||
| 148 | rpmloc = h | ||
| 149 | |||
| 150 | m = re.match("(.*)-(\d+.*)-(\d+\.\d+)\.(.+)\.rpm", os.path.basename(rpmloc)) | ||
| 151 | if m: | ||
| 152 | pkgname = m.group(1) | ||
| 153 | else: | ||
| 154 | pkgname = os.path.basename(rpmloc) | ||
| 155 | if self.output: | ||
| 156 | fmt = self._makefmt(percent) | ||
| 157 | msg = fmt % (self.headmsg, pkgname) | ||
| 158 | if msg != self.lastmsg: | ||
| 159 | self.lastmsg = msg | ||
| 160 | |||
| 161 | msger.info(msg) | ||
| 162 | |||
| 163 | if self.total_installed == self.total_actions: | ||
| 164 | msger.raw('') | ||
| 165 | msger.verbose('\n'.join(self.logString)) | ||
| 166 | |||
| 167 | elif what == rpm.RPMCALLBACK_UNINST_START: | ||
| 168 | pass | ||
| 169 | |||
| 170 | elif what == rpm.RPMCALLBACK_UNINST_PROGRESS: | ||
| 171 | pass | ||
| 172 | |||
| 173 | elif what == rpm.RPMCALLBACK_UNINST_STOP: | ||
| 174 | self.total_removed += 1 | ||
| 175 | |||
| 176 | elif what == rpm.RPMCALLBACK_REPACKAGE_START: | ||
| 177 | pass | ||
| 178 | |||
| 179 | elif what == rpm.RPMCALLBACK_REPACKAGE_STOP: | ||
| 180 | pass | ||
| 181 | |||
| 182 | elif what == rpm.RPMCALLBACK_REPACKAGE_PROGRESS: | ||
| 183 | pass | ||
| 184 | |||
| 185 | def readRpmHeader(ts, filename): | ||
| 186 | """ Read an rpm header. """ | ||
| 187 | |||
| 188 | fd = os.open(filename, os.O_RDONLY) | ||
| 189 | h = ts.hdrFromFdno(fd) | ||
| 190 | os.close(fd) | ||
| 191 | return h | ||
| 192 | |||
| 193 | def splitFilename(filename): | ||
| 194 | """ Pass in a standard style rpm fullname | ||
| 195 | |||
| 196 | Return a name, version, release, epoch, arch, e.g.:: | ||
| 197 | foo-1.0-1.i386.rpm returns foo, 1.0, 1, i386 | ||
| 198 | 1:bar-9-123a.ia64.rpm returns bar, 9, 123a, 1, ia64 | ||
| 199 | """ | ||
| 200 | |||
| 201 | if filename[-4:] == '.rpm': | ||
| 202 | filename = filename[:-4] | ||
| 203 | |||
| 204 | archIndex = filename.rfind('.') | ||
| 205 | arch = filename[archIndex+1:] | ||
| 206 | |||
| 207 | relIndex = filename[:archIndex].rfind('-') | ||
| 208 | rel = filename[relIndex+1:archIndex] | ||
| 209 | |||
| 210 | verIndex = filename[:relIndex].rfind('-') | ||
| 211 | ver = filename[verIndex+1:relIndex] | ||
| 212 | |||
| 213 | epochIndex = filename.find(':') | ||
| 214 | if epochIndex == -1: | ||
| 215 | epoch = '' | ||
| 216 | else: | ||
| 217 | epoch = filename[:epochIndex] | ||
| 218 | |||
| 219 | name = filename[epochIndex + 1:verIndex] | ||
| 220 | return name, ver, rel, epoch, arch | ||
| 221 | |||
| 222 | def getCanonX86Arch(arch): | ||
| 223 | # | ||
| 224 | if arch == "i586": | ||
| 225 | f = open("/proc/cpuinfo", "r") | ||
| 226 | lines = f.readlines() | ||
| 227 | f.close() | ||
| 228 | for line in lines: | ||
| 229 | if line.startswith("model name") and line.find("Geode(TM)") != -1: | ||
| 230 | return "geode" | ||
| 231 | return arch | ||
| 232 | # only athlon vs i686 isn't handled with uname currently | ||
| 233 | if arch != "i686": | ||
| 234 | return arch | ||
| 235 | |||
| 236 | # if we're i686 and AuthenticAMD, then we should be an athlon | ||
| 237 | f = open("/proc/cpuinfo", "r") | ||
| 238 | lines = f.readlines() | ||
| 239 | f.close() | ||
| 240 | for line in lines: | ||
| 241 | if line.startswith("vendor") and line.find("AuthenticAMD") != -1: | ||
| 242 | return "athlon" | ||
| 243 | # i686 doesn't guarantee cmov, but we depend on it | ||
| 244 | elif line.startswith("flags") and line.find("cmov") == -1: | ||
| 245 | return "i586" | ||
| 246 | |||
| 247 | return arch | ||
| 248 | |||
| 249 | def getCanonX86_64Arch(arch): | ||
| 250 | if arch != "x86_64": | ||
| 251 | return arch | ||
| 252 | |||
| 253 | vendor = None | ||
| 254 | f = open("/proc/cpuinfo", "r") | ||
| 255 | lines = f.readlines() | ||
| 256 | f.close() | ||
| 257 | for line in lines: | ||
| 258 | if line.startswith("vendor_id"): | ||
| 259 | vendor = line.split(':')[1] | ||
| 260 | break | ||
| 261 | if vendor is None: | ||
| 262 | return arch | ||
| 263 | |||
| 264 | if vendor.find("Authentic AMD") != -1 or vendor.find("AuthenticAMD") != -1: | ||
| 265 | return "amd64" | ||
| 266 | if vendor.find("GenuineIntel") != -1: | ||
| 267 | return "ia32e" | ||
| 268 | return arch | ||
| 269 | |||
| 270 | def getCanonArch(): | ||
| 271 | arch = os.uname()[4] | ||
| 272 | |||
| 273 | if (len(arch) == 4 and arch[0] == "i" and arch[2:4] == "86"): | ||
| 274 | return getCanonX86Arch(arch) | ||
| 275 | |||
| 276 | if arch == "x86_64": | ||
| 277 | return getCanonX86_64Arch(arch) | ||
| 278 | |||
| 279 | return arch | ||
| 280 | |||
| 281 | # Copy from libsatsolver:poolarch.c, with cleanup | ||
| 282 | archPolicies = { | ||
| 283 | "x86_64": "x86_64:i686:i586:i486:i386", | ||
| 284 | "i686": "i686:i586:i486:i386", | ||
| 285 | "i586": "i586:i486:i386", | ||
| 286 | "ia64": "ia64:i686:i586:i486:i386", | ||
| 287 | "armv7tnhl": "armv7tnhl:armv7thl:armv7nhl:armv7hl", | ||
| 288 | "armv7thl": "armv7thl:armv7hl", | ||
| 289 | "armv7nhl": "armv7nhl:armv7hl", | ||
| 290 | "armv7hl": "armv7hl", | ||
| 291 | "armv7l": "armv7l:armv6l:armv5tejl:armv5tel:armv5l:armv4tl:armv4l:armv3l", | ||
| 292 | "armv6l": "armv6l:armv5tejl:armv5tel:armv5l:armv4tl:armv4l:armv3l", | ||
| 293 | "armv5tejl": "armv5tejl:armv5tel:armv5l:armv4tl:armv4l:armv3l", | ||
| 294 | "armv5tel": "armv5tel:armv5l:armv4tl:armv4l:armv3l", | ||
| 295 | "armv5l": "armv5l:armv4tl:armv4l:armv3l", | ||
| 296 | } | ||
| 297 | |||
| 298 | # dict mapping arch -> ( multicompat, best personality, biarch personality ) | ||
| 299 | multilibArches = { | ||
| 300 | "x86_64": ( "athlon", "x86_64", "athlon" ), | ||
| 301 | } | ||
| 302 | |||
| 303 | # from yumUtils.py | ||
| 304 | arches = { | ||
| 305 | # ia32 | ||
| 306 | "athlon": "i686", | ||
| 307 | "i686": "i586", | ||
| 308 | "geode": "i586", | ||
| 309 | "i586": "i486", | ||
| 310 | "i486": "i386", | ||
| 311 | "i386": "noarch", | ||
| 312 | |||
| 313 | # amd64 | ||
| 314 | "x86_64": "athlon", | ||
| 315 | "amd64": "x86_64", | ||
| 316 | "ia32e": "x86_64", | ||
| 317 | |||
| 318 | # arm | ||
| 319 | "armv7tnhl": "armv7nhl", | ||
| 320 | "armv7nhl": "armv7hl", | ||
| 321 | "armv7hl": "noarch", | ||
| 322 | "armv7l": "armv6l", | ||
| 323 | "armv6l": "armv5tejl", | ||
| 324 | "armv5tejl": "armv5tel", | ||
| 325 | "armv5tel": "noarch", | ||
| 326 | |||
| 327 | #itanium | ||
| 328 | "ia64": "noarch", | ||
| 329 | } | ||
| 330 | |||
| 331 | def isMultiLibArch(arch=None): | ||
| 332 | """returns true if arch is a multilib arch, false if not""" | ||
| 333 | if arch is None: | ||
| 334 | arch = getCanonArch() | ||
| 335 | |||
| 336 | if not arches.has_key(arch): # or we could check if it is noarch | ||
| 337 | return False | ||
| 338 | |||
| 339 | if multilibArches.has_key(arch): | ||
| 340 | return True | ||
| 341 | |||
| 342 | if multilibArches.has_key(arches[arch]): | ||
| 343 | return True | ||
| 344 | |||
| 345 | return False | ||
| 346 | |||
| 347 | def getBaseArch(): | ||
| 348 | myarch = getCanonArch() | ||
| 349 | if not arches.has_key(myarch): | ||
| 350 | return myarch | ||
| 351 | |||
| 352 | if isMultiLibArch(arch=myarch): | ||
| 353 | if multilibArches.has_key(myarch): | ||
| 354 | return myarch | ||
| 355 | else: | ||
| 356 | return arches[myarch] | ||
| 357 | |||
| 358 | if arches.has_key(myarch): | ||
| 359 | basearch = myarch | ||
| 360 | value = arches[basearch] | ||
| 361 | while value != 'noarch': | ||
| 362 | basearch = value | ||
| 363 | value = arches[basearch] | ||
| 364 | |||
| 365 | return basearch | ||
| 366 | |||
| 367 | def checkRpmIntegrity(bin_rpm, package): | ||
| 368 | return runner.quiet([bin_rpm, "-K", "--nosignature", package]) | ||
| 369 | |||
| 370 | def checkSig(ts, package): | ||
| 371 | """ Takes a transaction set and a package, check it's sigs, | ||
| 372 | return 0 if they are all fine | ||
| 373 | return 1 if the gpg key can't be found | ||
| 374 | return 2 if the header is in someway damaged | ||
| 375 | return 3 if the key is not trusted | ||
| 376 | return 4 if the pkg is not gpg or pgp signed | ||
| 377 | """ | ||
| 378 | |||
| 379 | value = 0 | ||
| 380 | currentflags = ts.setVSFlags(0) | ||
| 381 | fdno = os.open(package, os.O_RDONLY) | ||
| 382 | try: | ||
| 383 | hdr = ts.hdrFromFdno(fdno) | ||
| 384 | |||
| 385 | except rpm.error, e: | ||
| 386 | if str(e) == "public key not availaiable": | ||
| 387 | value = 1 | ||
| 388 | if str(e) == "public key not available": | ||
| 389 | value = 1 | ||
| 390 | if str(e) == "public key not trusted": | ||
| 391 | value = 3 | ||
| 392 | if str(e) == "error reading package header": | ||
| 393 | value = 2 | ||
| 394 | else: | ||
| 395 | error, siginfo = getSigInfo(hdr) | ||
| 396 | if error == 101: | ||
| 397 | os.close(fdno) | ||
| 398 | del hdr | ||
| 399 | value = 4 | ||
| 400 | else: | ||
| 401 | del hdr | ||
| 402 | |||
| 403 | try: | ||
| 404 | os.close(fdno) | ||
| 405 | except OSError: | ||
| 406 | pass | ||
| 407 | |||
| 408 | ts.setVSFlags(currentflags) # put things back like they were before | ||
| 409 | return value | ||
| 410 | |||
| 411 | def getSigInfo(hdr): | ||
| 412 | """ checks signature from an hdr hand back signature information and/or | ||
| 413 | an error code | ||
| 414 | """ | ||
| 415 | |||
| 416 | import locale | ||
| 417 | locale.setlocale(locale.LC_ALL, 'C') | ||
| 418 | |||
| 419 | string = '%|DSAHEADER?{%{DSAHEADER:pgpsig}}:{%|RSAHEADER?{%{RSAHEADER:pgpsig}}:{%|SIGGPG?{%{SIGGPG:pgpsig}}:{%|SIGPGP?{%{SIGPGP:pgpsig}}:{(none)}|}|}|}|' | ||
| 420 | siginfo = hdr.sprintf(string) | ||
| 421 | if siginfo != '(none)': | ||
| 422 | error = 0 | ||
| 423 | sigtype, sigdate, sigid = siginfo.split(',') | ||
| 424 | else: | ||
| 425 | error = 101 | ||
| 426 | sigtype = 'MD5' | ||
| 427 | sigdate = 'None' | ||
| 428 | sigid = 'None' | ||
| 429 | |||
| 430 | infotuple = (sigtype, sigdate, sigid) | ||
| 431 | return error, infotuple | ||
| 432 | |||
| 433 | def checkRepositoryEULA(name, repo): | ||
| 434 | """ This function is to check the EULA file if provided. | ||
| 435 | return True: no EULA or accepted | ||
| 436 | return False: user declined the EULA | ||
| 437 | """ | ||
| 438 | |||
| 439 | import tempfile | ||
| 440 | import shutil | ||
| 441 | import urlparse | ||
| 442 | import urllib2 as u2 | ||
| 443 | import httplib | ||
| 444 | from mic.utils.errors import CreatorError | ||
| 445 | |||
| 446 | def _check_and_download_url(u2opener, url, savepath): | ||
| 447 | try: | ||
| 448 | if u2opener: | ||
| 449 | f = u2opener.open(url) | ||
| 450 | else: | ||
| 451 | f = u2.urlopen(url) | ||
| 452 | except u2.HTTPError, httperror: | ||
| 453 | if httperror.code in (404, 503): | ||
| 454 | return None | ||
| 455 | else: | ||
| 456 | raise CreatorError(httperror) | ||
| 457 | except OSError, oserr: | ||
| 458 | if oserr.errno == 2: | ||
| 459 | return None | ||
| 460 | else: | ||
| 461 | raise CreatorError(oserr) | ||
| 462 | except IOError, oserr: | ||
| 463 | if hasattr(oserr, "reason") and oserr.reason.errno == 2: | ||
| 464 | return None | ||
| 465 | else: | ||
| 466 | raise CreatorError(oserr) | ||
| 467 | except u2.URLError, err: | ||
| 468 | raise CreatorError(err) | ||
| 469 | except httplib.HTTPException, e: | ||
| 470 | raise CreatorError(e) | ||
| 471 | |||
| 472 | # save to file | ||
| 473 | licf = open(savepath, "w") | ||
| 474 | licf.write(f.read()) | ||
| 475 | licf.close() | ||
| 476 | f.close() | ||
| 477 | |||
| 478 | return savepath | ||
| 479 | |||
| 480 | def _pager_file(savepath): | ||
| 481 | |||
| 482 | if os.path.splitext(savepath)[1].upper() in ('.HTM', '.HTML'): | ||
| 483 | pagers = ('w3m', 'links', 'lynx', 'less', 'more') | ||
| 484 | else: | ||
| 485 | pagers = ('less', 'more') | ||
| 486 | |||
| 487 | file_showed = False | ||
| 488 | for pager in pagers: | ||
| 489 | cmd = "%s %s" % (pager, savepath) | ||
| 490 | try: | ||
| 491 | os.system(cmd) | ||
| 492 | except OSError: | ||
| 493 | continue | ||
| 494 | else: | ||
| 495 | file_showed = True | ||
| 496 | break | ||
| 497 | |||
| 498 | if not file_showed: | ||
| 499 | f = open(savepath) | ||
| 500 | msger.raw(f.read()) | ||
| 501 | f.close() | ||
| 502 | msger.pause() | ||
| 503 | |||
| 504 | # when proxy needed, make urllib2 follow it | ||
| 505 | proxy = repo.proxy | ||
| 506 | proxy_username = repo.proxy_username | ||
| 507 | proxy_password = repo.proxy_password | ||
| 508 | |||
| 509 | if not proxy: | ||
| 510 | proxy = get_proxy_for(repo.baseurl[0]) | ||
| 511 | |||
| 512 | handlers = [] | ||
| 513 | auth_handler = u2.HTTPBasicAuthHandler(u2.HTTPPasswordMgrWithDefaultRealm()) | ||
| 514 | u2opener = None | ||
| 515 | if proxy: | ||
| 516 | if proxy_username: | ||
| 517 | proxy_netloc = urlparse.urlsplit(proxy).netloc | ||
| 518 | if proxy_password: | ||
| 519 | proxy_url = 'http://%s:%s@%s' % (proxy_username, proxy_password, proxy_netloc) | ||
| 520 | else: | ||
| 521 | proxy_url = 'http://%s@%s' % (proxy_username, proxy_netloc) | ||
| 522 | else: | ||
| 523 | proxy_url = proxy | ||
| 524 | |||
| 525 | proxy_support = u2.ProxyHandler({'http': proxy_url, | ||
| 526 | 'https': proxy_url, | ||
| 527 | 'ftp': proxy_url}) | ||
| 528 | handlers.append(proxy_support) | ||
| 529 | |||
| 530 | # download all remote files to one temp dir | ||
| 531 | baseurl = None | ||
| 532 | repo_lic_dir = tempfile.mkdtemp(prefix = 'repolic') | ||
| 533 | |||
| 534 | for url in repo.baseurl: | ||
| 535 | tmphandlers = handlers[:] | ||
| 536 | |||
| 537 | (scheme, host, path, parm, query, frag) = urlparse.urlparse(url.rstrip('/') + '/') | ||
| 538 | if scheme not in ("http", "https", "ftp", "ftps", "file"): | ||
| 539 | raise CreatorError("Error: invalid url %s" % url) | ||
| 540 | |||
| 541 | if '@' in host: | ||
| 542 | try: | ||
| 543 | user_pass, host = host.split('@', 1) | ||
| 544 | if ':' in user_pass: | ||
| 545 | user, password = user_pass.split(':', 1) | ||
| 546 | except ValueError, e: | ||
| 547 | raise CreatorError('Bad URL: %s' % url) | ||
| 548 | |||
| 549 | msger.verbose("adding HTTP auth: %s, XXXXXXXX" %(user)) | ||
| 550 | auth_handler.add_password(None, host, user, password) | ||
| 551 | tmphandlers.append(auth_handler) | ||
| 552 | url = scheme + "://" + host + path + parm + query + frag | ||
| 553 | |||
| 554 | if tmphandlers: | ||
| 555 | u2opener = u2.build_opener(*tmphandlers) | ||
| 556 | |||
| 557 | # try to download | ||
| 558 | repo_eula_url = urlparse.urljoin(url, "LICENSE.txt") | ||
| 559 | repo_eula_path = _check_and_download_url( | ||
| 560 | u2opener, | ||
| 561 | repo_eula_url, | ||
| 562 | os.path.join(repo_lic_dir, repo.id + '_LICENSE.txt')) | ||
| 563 | if repo_eula_path: | ||
| 564 | # found | ||
| 565 | baseurl = url | ||
| 566 | break | ||
| 567 | |||
| 568 | if not baseurl: | ||
| 569 | shutil.rmtree(repo_lic_dir) #cleanup | ||
| 570 | return True | ||
| 571 | |||
| 572 | # show the license file | ||
| 573 | msger.info('For the software packages in this yum repo:') | ||
| 574 | msger.info(' %s: %s' % (name, baseurl)) | ||
| 575 | msger.info('There is an "End User License Agreement" file that need to be checked.') | ||
| 576 | msger.info('Please read the terms and conditions outlined in it and answer the followed qustions.') | ||
| 577 | msger.pause() | ||
| 578 | |||
| 579 | _pager_file(repo_eula_path) | ||
| 580 | |||
| 581 | # Asking for the "Accept/Decline" | ||
| 582 | if not msger.ask('Would you agree to the terms and conditions outlined in the above End User License Agreement?'): | ||
| 583 | msger.warning('Will not install pkgs from this repo.') | ||
| 584 | shutil.rmtree(repo_lic_dir) #cleanup | ||
| 585 | return False | ||
| 586 | |||
| 587 | # try to find support_info.html for extra infomation | ||
| 588 | repo_info_url = urlparse.urljoin(baseurl, "support_info.html") | ||
| 589 | repo_info_path = _check_and_download_url( | ||
| 590 | u2opener, | ||
| 591 | repo_info_url, | ||
| 592 | os.path.join(repo_lic_dir, repo.id + '_support_info.html')) | ||
| 593 | if repo_info_path: | ||
| 594 | msger.info('There is one more file in the repo for additional support information, please read it') | ||
| 595 | msger.pause() | ||
| 596 | _pager_file(repo_info_path) | ||
| 597 | |||
| 598 | #cleanup | ||
| 599 | shutil.rmtree(repo_lic_dir) | ||
| 600 | return True | ||
