Package yum :: Module config
[hide private]
[frames] | no frames]

Source Code for Module yum.config

  1  #!/usr/bin/python -t 
  2   
  3  # This program is free software; you can redistribute it and/or modify 
  4  # it under the terms of the GNU General Public License as published by 
  5  # the Free Software Foundation; either version 2 of the License, or 
  6  # (at your option) any later version. 
  7  # 
  8  # This program is distributed in the hope that it will be useful, 
  9  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 10  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 11  # GNU Library General Public License for more details. 
 12  # 
 13  # You should have received a copy of the GNU General Public License 
 14  # along with this program; if not, write to the Free Software 
 15  # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
 16  # Copyright 2002 Duke University  
 17   
 18  """ 
 19  Configuration parser and default values for yum. 
 20  """ 
 21  _use_iniparse = True 
 22   
 23  import os 
 24  import sys 
 25  import warnings 
 26  import rpm 
 27  import copy 
 28  import urlparse 
 29  import shlex 
 30  from parser import ConfigPreProcessor, varReplace 
 31  try: 
 32      from iniparse import INIConfig 
 33      from iniparse.compat import NoSectionError, NoOptionError, ParsingError 
 34      from iniparse.compat import RawConfigParser as ConfigParser 
 35  except ImportError: 
 36      _use_iniparse = False 
 37  if not _use_iniparse: 
 38      from ConfigParser import NoSectionError, NoOptionError, ParsingError 
 39      from ConfigParser import ConfigParser 
 40  import rpmUtils.transaction 
 41  import Errors 
 42  import types 
 43  from misc import get_uuid 
 44   
 45  # Alter/patch these to change the default checking... 
 46  __pkgs_gpgcheck_default__ = False 
 47  __repo_gpgcheck_default__ = False 
 48   
49 -class Option(object):
50 ''' 51 This class handles a single Yum configuration file option. Create 52 subclasses for each type of supported configuration option. 53 54 Python descriptor foo (__get__ and __set__) is used to make option 55 definition easy and consise. 56 ''' 57
58 - def __init__(self, default=None):
59 self._setattrname() 60 self.inherit = False 61 self.default = default
62
63 - def _setattrname(self):
64 '''Calculate the internal attribute name used to store option state in 65 configuration instances. 66 ''' 67 self._attrname = '__opt%d' % id(self)
68
69 - def __get__(self, obj, objtype):
70 '''Called when the option is read (via the descriptor protocol). 71 72 @param obj: The configuration instance to modify. 73 @param objtype: The type of the config instance (not used). 74 @return: The parsed option value or the default value if the value 75 wasn't set in the configuration file. 76 ''' 77 # xemacs highlighting hack: ' 78 if obj is None: 79 return self 80 81 return getattr(obj, self._attrname, None)
82
83 - def __set__(self, obj, value):
84 '''Called when the option is set (via the descriptor protocol). 85 86 @param obj: The configuration instance to modify. 87 @param value: The value to set the option to. 88 @return: Nothing. 89 ''' 90 # Only try to parse if its a string 91 if isinstance(value, basestring): 92 try: 93 value = self.parse(value) 94 except ValueError, e: 95 # Add the field name onto the error 96 raise ValueError('Error parsing "%s = %r": %s' % (self._optname, 97 value, str(e))) 98 setattr(obj, self._attrname, value)
99
100 - def setup(self, obj, name):
101 '''Initialise the option for a config instance. 102 This must be called before the option can be set or retrieved. 103 104 @param obj: BaseConfig (or subclass) instance. 105 @param name: Name of the option. 106 ''' 107 self._optname = name 108 setattr(obj, self._attrname, copy.copy(self.default))
109
110 - def clone(self):
111 '''Return a safe copy of this Option instance 112 ''' 113 new = copy.copy(self) 114 new._setattrname() 115 return new
116
117 - def parse(self, s):
118 '''Parse the string value to the Option's native value. 119 120 @param s: Raw string value to parse. 121 @return: Validated native value. 122 123 Will raise ValueError if there was a problem parsing the string. 124 Subclasses should override this. 125 ''' 126 return s
127
128 - def tostring(self, value):
129 '''Convert the Option's native value to a string value. 130 131 @param value: Native option value. 132 @return: String representation of input. 133 134 This does the opposite of the parse() method above. 135 Subclasses should override this. 136 ''' 137 return str(value)
138
139 -def Inherit(option_obj):
140 '''Clone an Option instance for the purposes of inheritance. The returned 141 instance has all the same properties as the input Option and shares items 142 such as the default value. Use this to avoid redefinition of reused 143 options. 144 145 @param option_obj: Option instance to inherit. 146 @return: New Option instance inherited from the input. 147 ''' 148 new_option = option_obj.clone() 149 new_option.inherit = True 150 return new_option
151
152 -class ListOption(Option):
153 154 """ 155 An option containing a list of strings. 156 """ 157
158 - def __init__(self, default=None):
159 if default is None: 160 default = [] 161 super(ListOption, self).__init__(default)
162
163 - def parse(self, s):
164 """Converts a string from the config file to a workable list 165 166 Commas and spaces are used as separators for the list 167 """ 168 # we need to allow for the '\n[whitespace]' continuation - easier 169 # to sub the \n with a space and then read the lines 170 s = s.replace('\n', ' ') 171 s = s.replace(',', ' ') 172 return s.split()
173
174 - def tostring(self, value):
175 return '\n '.join(value)
176
177 -class UrlOption(Option):
178 ''' 179 This option handles lists of URLs with validation of the URL scheme. 180 ''' 181
182 - def __init__(self, default=None, schemes=('http', 'ftp', 'file', 'https'), 183 allow_none=False):
184 super(UrlOption, self).__init__(default) 185 self.schemes = schemes 186 self.allow_none = allow_none
187
188 - def parse(self, url):
189 url = url.strip() 190 191 # Handle the "_none_" special case 192 if url.lower() == '_none_': 193 if self.allow_none: 194 return None 195 else: 196 raise ValueError('"_none_" is not a valid value') 197 198 # Check that scheme is valid 199 (s,b,p,q,f,o) = urlparse.urlparse(url) 200 if s not in self.schemes: 201 raise ValueError('URL must be %s not "%s"' % (self._schemelist(), s)) 202 203 return url
204
205 - def _schemelist(self):
206 '''Return a user friendly list of the allowed schemes 207 ''' 208 if len(self.schemes) < 1: 209 return 'empty' 210 elif len(self.schemes) == 1: 211 return self.schemes[0] 212 else: 213 return '%s or %s' % (', '.join(self.schemes[:-1]), self.schemes[-1])
214
215 -class UrlListOption(ListOption):
216 ''' 217 Option for handling lists of URLs with validation of the URL scheme. 218 ''' 219
220 - def __init__(self, default=None, schemes=('http', 'ftp', 'file', 'https')):
221 super(UrlListOption, self).__init__(default) 222 223 # Hold a UrlOption instance to assist with parsing 224 self._urloption = UrlOption(schemes=schemes)
225
226 - def parse(self, s):
227 out = [] 228 s = s.replace('\n', ' ') 229 s = s.replace(',', ' ') 230 items = [ item.replace(' ', '%20') for item in shlex.split(s) ] 231 s = ' '.join(items) 232 for url in super(UrlListOption, self).parse(s): 233 out.append(self._urloption.parse(url)) 234 return out
235 236
237 -class IntOption(Option):
238 239 """ 240 An option representing an integer value. 241 """ 242
243 - def __init__(self, default=None, range_min=None, range_max=None):
244 super(IntOption, self).__init__(default) 245 self._range_min = range_min 246 self._range_max = range_max
247
248 - def parse(self, s):
249 try: 250 val = int(s) 251 except (ValueError, TypeError), e: 252 raise ValueError('invalid integer value') 253 if self._range_max is not None and val > self._range_max: 254 raise ValueError('out of range integer value') 255 if self._range_min is not None and val < self._range_min: 256 raise ValueError('out of range integer value') 257 return val
258
259 -class PositiveIntOption(IntOption):
260 261 """ 262 An option representing a positive integer value, where 0 can have a special 263 represention. 264 """ 265
266 - def __init__(self, default=None, range_min=0, range_max=None, 267 names_of_0=None):
268 super(PositiveIntOption, self).__init__(default, range_min, range_max) 269 self._names0 = names_of_0
270
271 - def parse(self, s):
272 if s in self._names0: 273 return 0 274 return super(PositiveIntOption, self).parse(s)
275
276 -class SecondsOption(Option):
277 278 """ 279 An option representing an integer value of seconds, or a human readable 280 variation specifying days, hours, minutes or seconds until something 281 happens. Works like BytesOption. 282 Note that due to historical president -1 means "never", so this accepts 283 that and allows the word never too. 284 285 Valid inputs: 100, 1.5m, 90s, 1.2d, 1d, 0xF, 0.1, -1, never 286 Invalid inputs: -10, -0.1, 45.6Z, 1d6h, 1day, 1y 287 288 Return value will always be an integer 289 """ 290 MULTS = {'d': 60 * 60 * 24, 'h' : 60 * 60, 'm' : 60, 's': 1} 291
292 - def parse(self, s):
293 if len(s) < 1: 294 raise ValueError("no value specified") 295 296 if s == "-1" or s == "never": # Special cache timeout, meaning never 297 return -1 298 if s[-1].isalpha(): 299 n = s[:-1] 300 unit = s[-1].lower() 301 mult = self.MULTS.get(unit, None) 302 if not mult: 303 raise ValueError("unknown unit '%s'" % unit) 304 else: 305 n = s 306 mult = 1 307 308 try: 309 n = float(n) 310 except (ValueError, TypeError), e: 311 raise ValueError('invalid value') 312 313 if n < 0: 314 raise ValueError("seconds value may not be negative") 315 316 return int(n * mult)
317
318 -class BoolOption(Option):
319 320 """ 321 An option representing a boolean value. 322 323 The value can be one of 0, 1, yes, no, true, or false. 324 """ 325
326 - def parse(self, s):
327 s = s.lower() 328 if s in ('0', 'no', 'false'): 329 return False 330 elif s in ('1', 'yes', 'true'): 331 return True 332 else: 333 raise ValueError('invalid boolean value')
334
335 - def tostring(self, value):
336 if value: 337 return "1" 338 else: 339 return "0"
340
341 -class FloatOption(Option):
342 """ 343 An option representing a numeric float value. 344 """
345 - def parse(self, s):
346 try: 347 return float(s.strip()) 348 except (ValueError, TypeError): 349 raise ValueError('invalid float value')
350
351 -class SelectionOption(Option):
352 '''Handles string values where only specific values are allowed 353 '''
354 - def __init__(self, default=None, allowed=(), mapper={}):
355 super(SelectionOption, self).__init__(default) 356 self._allowed = allowed 357 self._mapper = mapper
358
359 - def parse(self, s):
360 if s in self._mapper: 361 s = self._mapper[s] 362 if s not in self._allowed: 363 raise ValueError('"%s" is not an allowed value' % s) 364 return s
365
366 -class CaselessSelectionOption(SelectionOption):
367 ''' Mainly for compat. with BoolOption, works like SelectionOption but 368 lowers input case. ''' 369
370 - def parse(self, s):
371 return super(CaselessSelectionOption, self).parse(s.lower())
372
373 -class BytesOption(Option):
374 375 """ 376 An option representing a value in bytes. 377 378 The value may be given in bytes, kilobytes, megabytes, or gigabytes. 379 """ 380 # Multipliers for unit symbols 381 MULTS = { 382 'k': 1024, 383 'm': 1024*1024, 384 'g': 1024*1024*1024, 385 } 386
387 - def parse(self, s):
388 """Parse a friendly bandwidth option to bytes 389 390 The input should be a string containing a (possibly floating point) 391 number followed by an optional single character unit. Valid units are 392 'k', 'M', 'G'. Case is ignored. 393 394 Valid inputs: 100, 123M, 45.6k, 12.4G, 100K, 786.3, 0 395 Invalid inputs: -10, -0.1, 45.6L, 123Mb 396 397 Return value will always be an integer 398 399 1k = 1024 bytes. 400 401 ValueError will be raised if the option couldn't be parsed. 402 """ 403 if len(s) < 1: 404 raise ValueError("no value specified") 405 406 if s[-1].isalpha(): 407 n = s[:-1] 408 unit = s[-1].lower() 409 mult = self.MULTS.get(unit, None) 410 if not mult: 411 raise ValueError("unknown unit '%s'" % unit) 412 else: 413 n = s 414 mult = 1 415 416 try: 417 n = float(n) 418 except ValueError: 419 raise ValueError("couldn't convert '%s' to number" % n) 420 421 if n < 0: 422 raise ValueError("bytes value may not be negative") 423 424 return int(n * mult)
425
426 -class ThrottleOption(BytesOption):
427 428 """ 429 An option representing a bandwidth throttle value. See 430 ThrottleOption.parse for acceptable input values. 431 """ 432
433 - def parse(self, s):
434 """Get a throttle option. 435 436 Input may either be a percentage or a "friendly bandwidth value" as 437 accepted by the BytesOption. 438 439 Valid inputs: 100, 50%, 80.5%, 123M, 45.6k, 12.4G, 100K, 786.0, 0 440 Invalid inputs: 100.1%, -4%, -500 441 442 Return value will be a int if a bandwidth value was specified or a 443 float if a percentage was given. 444 445 ValueError will be raised if input couldn't be parsed. 446 """ 447 if len(s) < 1: 448 raise ValueError("no value specified") 449 450 if s[-1] == '%': 451 n = s[:-1] 452 try: 453 n = float(n) 454 except ValueError: 455 raise ValueError("couldn't convert '%s' to number" % n) 456 if n < 0 or n > 100: 457 raise ValueError("percentage is out of range") 458 return n / 100.0 459 else: 460 return BytesOption.parse(self, s)
461
462 -class BaseConfig(object):
463 ''' 464 Base class for storing configuration definitions. Subclass when creating 465 your own definitons. 466 ''' 467
468 - def __init__(self):
469 self._section = None 470 471 for name in self.iterkeys(): 472 option = self.optionobj(name) 473 option.setup(self, name)
474
475 - def __str__(self):
476 out = [] 477 out.append('[%s]' % self._section) 478 for name, value in self.iteritems(): 479 out.append('%s: %r' % (name, value)) 480 return '\n'.join(out)
481
482 - def populate(self, parser, section, parent=None):
483 '''Set option values from a INI file section. 484 485 @param parser: ConfParser instance (or subclass) 486 @param section: INI file section to read use. 487 @param parent: Optional parent BaseConfig (or subclass) instance to use 488 when doing option value inheritance. 489 ''' 490 self.cfg = parser 491 self._section = section 492 493 if parser.has_section(section): 494 opts = set(parser.options(section)) 495 else: 496 opts = set() 497 for name in self.iterkeys(): 498 option = self.optionobj(name) 499 value = None 500 if name in opts: 501 value = parser.get(section, name) 502 else: 503 # No matching option in this section, try inheriting 504 if parent and option.inherit: 505 value = getattr(parent, name) 506 507 if value is not None: 508 setattr(self, name, value)
509
510 - def optionobj(cls, name, exceptions=True):
511 '''Return the Option instance for the given name 512 ''' 513 obj = getattr(cls, name, None) 514 if isinstance(obj, Option): 515 return obj 516 elif exceptions: 517 raise KeyError 518 else: 519 return None
520 optionobj = classmethod(optionobj) 521
522 - def isoption(cls, name):
523 '''Return True if the given name refers to a defined option 524 ''' 525 return cls.optionobj(name, exceptions=False) is not None
526 isoption = classmethod(isoption) 527
528 - def iterkeys(self):
529 '''Yield the names of all defined options in the instance. 530 ''' 531 for name in dir(self): 532 if self.isoption(name): 533 yield name
534
535 - def iteritems(self):
536 '''Yield (name, value) pairs for every option in the instance. 537 538 The value returned is the parsed, validated option value. 539 ''' 540 # Use dir() so that we see inherited options too 541 for name in self.iterkeys(): 542 yield (name, getattr(self, name))
543
544 - def write(self, fileobj, section=None, always=()):
545 '''Write out the configuration to a file-like object 546 547 @param fileobj: File-like object to write to 548 @param section: Section name to use. If not-specified the section name 549 used during parsing will be used. 550 @param always: A sequence of option names to always write out. 551 Options not listed here will only be written out if they are at 552 non-default values. Set to None to dump out all options. 553 ''' 554 # Write section heading 555 if section is None: 556 if self._section is None: 557 raise ValueError("not populated, don't know section") 558 section = self._section 559 560 # Updated the ConfigParser with the changed values 561 cfgOptions = self.cfg.options(section) 562 for name,value in self.iteritems(): 563 option = self.optionobj(name) 564 if always is None or name in always or option.default != value or name in cfgOptions : 565 self.cfg.set(section,name, option.tostring(value)) 566 # write the updated ConfigParser to the fileobj. 567 self.cfg.write(fileobj)
568
569 - def getConfigOption(self, option, default=None):
570 warnings.warn('getConfigOption() will go away in a future version of Yum.\n' 571 'Please access option values as attributes or using getattr().', 572 DeprecationWarning) 573 if hasattr(self, option): 574 return getattr(self, option) 575 return default
576
577 - def setConfigOption(self, option, value):
578 warnings.warn('setConfigOption() will go away in a future version of Yum.\n' 579 'Please set option values as attributes or using setattr().', 580 DeprecationWarning) 581 if hasattr(self, option): 582 setattr(self, option, value) 583 else: 584 raise Errors.ConfigError, 'No such option %s' % option
585
586 -class StartupConf(BaseConfig):
587 ''' 588 Configuration option definitions for yum.conf's [main] section that are 589 required early in the initialisation process or before the other [main] 590 options can be parsed. 591 ''' 592 # xemacs highlighting hack: ' 593 debuglevel = IntOption(2, 0, 10) 594 errorlevel = IntOption(2, 0, 10) 595 596 distroverpkg = Option('redhat-release') 597 installroot = Option('/') 598 config_file_path = Option('/etc/yum/yum.conf') 599 plugins = BoolOption(False) 600 pluginpath = ListOption(['/usr/share/yum-plugins', '/usr/lib/yum-plugins']) 601 pluginconfpath = ListOption(['/etc/yum/pluginconf.d']) 602 gaftonmode = BoolOption(False) 603 syslog_ident = Option() 604 syslog_facility = Option('LOG_DAEMON') 605 persistdir = Option('/var/lib/yum')
606
607 -class YumConf(StartupConf):
608 ''' 609 Configuration option definitions for yum.conf\'s [main] section. 610 611 Note: see also options inherited from StartupConf 612 ''' 613 retries = PositiveIntOption(10, names_of_0=["<forever>"]) 614 recent = IntOption(7, range_min=0) 615 616 cachedir = Option('/var/cache/yum') 617 618 keepcache = BoolOption(True) 619 logfile = Option('/var/log/yum.log') 620 reposdir = ListOption(['/etc/yum/repos.d', '/etc/yum.repos.d']) 621 622 commands = ListOption() 623 exclude = ListOption() 624 failovermethod = Option('roundrobin') 625 proxy = UrlOption(schemes=('http', 'ftp', 'https'), allow_none=True) 626 proxy_username = Option() 627 proxy_password = Option() 628 installonlypkgs = ListOption(['kernel', 'kernel-bigmem', 629 'kernel-enterprise','kernel-smp', 'kernel-modules', 'kernel-debug', 630 'kernel-unsupported', 'kernel-source', 'kernel-devel', 'kernel-PAE', 631 'kernel-PAE-debug']) 632 # NOTE: If you set this to 2, then because it keeps the current kernel it 633 # means if you ever install an "old" kernel it'll get rid of the newest one 634 # so you probably want to use 3 as a minimum ... if you turn it on. 635 installonly_limit = PositiveIntOption(0, range_min=2, 636 names_of_0=["0", "<off>"]) 637 kernelpkgnames = ListOption(['kernel','kernel-smp', 'kernel-enterprise', 638 'kernel-bigmem', 'kernel-BOOT', 'kernel-PAE', 'kernel-PAE-debug']) 639 exactarchlist = ListOption(['kernel', 'kernel-smp', 640 'kernel-hugemem', 'kernel-enterprise', 'kernel-bigmem', 641 'kernel-devel', 'kernel-PAE', 'kernel-PAE-debug']) 642 tsflags = ListOption() 643 644 assumeyes = BoolOption(False) 645 alwaysprompt = BoolOption(True) 646 exactarch = BoolOption(True) 647 tolerant = BoolOption(True) 648 diskspacecheck = BoolOption(True) 649 overwrite_groups = BoolOption(False) 650 keepalive = BoolOption(True) 651 # FIXME: rename gpgcheck to pkgs_gpgcheck 652 gpgcheck = BoolOption(__pkgs_gpgcheck_default__) 653 repo_gpgcheck = BoolOption(__repo_gpgcheck_default__) 654 obsoletes = BoolOption(True) 655 showdupesfromrepos = BoolOption(False) 656 enabled = BoolOption(True) 657 enablegroups = BoolOption(True) 658 enable_group_conditionals = BoolOption(True) 659 group_package_types = ListOption(['mandatory', 'default']) 660 661 timeout = FloatOption(30.0) # FIXME: Should use variation of SecondsOption 662 663 bandwidth = BytesOption(0) 664 throttle = ThrottleOption(0) 665 666 http_caching = SelectionOption('all', ('none', 'packages', 'all')) 667 metadata_expire = SecondsOption(60 * 60 * 6) # Time in seconds (6h). 668 # Time in seconds (1 day). NOTE: This isn't used when using metalinks 669 mirrorlist_expire = SecondsOption(60 * 60 * 24) 670 rpm_check_debug = BoolOption(True) 671 disable_excludes = ListOption() 672 skip_broken = BoolOption(False) 673 # Note that "instant" is the old behaviour, but group:primary is very 674 # similar but better :). 675 mdpolicy = ListOption(['group:primary']) 676 # ('instant', 'group:all', 'group:main', 'group:small', 'group:primary')) 677 multilib_policy = SelectionOption('all',('best', 'all')) 678 # all == install any/all arches you can 679 # best == use the 'best arch' for the system 680 681 bugtracker_url = Option('http://yum.baseurl.org/report') 682 683 color = SelectionOption('auto', ('auto', 'never', 'always'), 684 mapper={'on' : 'always', 'yes' : 'always', 685 '1' : 'always', 'true' : 'always', 686 'off' : 'never', 'no' : 'never', 687 '0' : 'never', 'false' : 'never', 688 'tty' : 'auto', 'if-tty' : 'auto'}) 689 color_list_installed_older = Option('bold') 690 color_list_installed_newer = Option('bold,yellow') 691 color_list_installed_reinstall = Option('normal') 692 color_list_installed_extra = Option('bold,red') 693 694 color_list_available_upgrade = Option('bold,blue') 695 color_list_available_downgrade = Option('dim,cyan') 696 color_list_available_reinstall = Option('bold,underline,green') 697 color_list_available_install = Option('normal') 698 699 color_update_installed = Option('normal') 700 color_update_local = Option('bold') 701 color_update_remote = Option('normal') 702 703 color_search_match = Option('bold') 704 705 sslcacert = Option() 706 sslverify = BoolOption(True) 707 sslclientcert = Option() 708 sslclientkey = Option() 709 710 history_record = BoolOption(True) 711 history_record_packages = ListOption(['yum', 'rpm']) 712 713 rpmverbosity = Option('info') 714 715 _reposlist = [] 716
717 - def dump(self):
718 output = '[main]\n' 719 # we exclude all vars which start with _ or are in this list: 720 excluded_vars = ('cfg', 'uid', 'yumvar', 'progress_obj', 'failure_obj', 721 'disable_excludes', 'config_file_age', 'config_file_path', 722 ) 723 for attr in dir(self): 724 if attr.startswith('_'): 725 continue 726 if attr in excluded_vars: 727 continue 728 if isinstance(getattr(self, attr), types.MethodType): 729 continue 730 res = getattr(self, attr) 731 if not res: 732 res = '' 733 if type(res) == types.ListType: 734 res = ',\n '.join(res) 735 output = output + '%s = %s\n' % (attr, res) 736 737 return output
738
739 -class RepoConf(BaseConfig):
740 ''' 741 Option definitions for repository INI file sections. 742 ''' 743 744 __cached_keys = set()
745 - def iterkeys(self):
746 '''Yield the names of all defined options in the instance. 747 ''' 748 ck = self.__cached_keys 749 if not isinstance(self, RepoConf): 750 ck = set() 751 if not ck: 752 ck.update(list(BaseConfig.iterkeys(self))) 753 754 for name in self.__cached_keys: 755 yield name
756 757 name = Option() 758 enabled = Inherit(YumConf.enabled) 759 baseurl = UrlListOption() 760 mirrorlist = UrlOption() 761 metalink = UrlOption() 762 mediaid = Option() 763 gpgkey = UrlListOption() 764 exclude = ListOption() 765 includepkgs = ListOption() 766 767 proxy = Inherit(YumConf.proxy) 768 proxy_username = Inherit(YumConf.proxy_username) 769 proxy_password = Inherit(YumConf.proxy_password) 770 retries = Inherit(YumConf.retries) 771 failovermethod = Inherit(YumConf.failovermethod) 772 773 # FIXME: rename gpgcheck to pkgs_gpgcheck 774 gpgcheck = Inherit(YumConf.gpgcheck) 775 repo_gpgcheck = Inherit(YumConf.repo_gpgcheck) 776 keepalive = Inherit(YumConf.keepalive) 777 enablegroups = Inherit(YumConf.enablegroups) 778 779 bandwidth = Inherit(YumConf.bandwidth) 780 throttle = Inherit(YumConf.throttle) 781 timeout = Inherit(YumConf.timeout) 782 http_caching = Inherit(YumConf.http_caching) 783 metadata_expire = Inherit(YumConf.metadata_expire) 784 mirrorlist_expire = Inherit(YumConf.mirrorlist_expire) 785 # NOTE: metalink expire _must_ be the same as metadata_expire, due to the 786 # checksumming of the repomd.xml. 787 mdpolicy = Inherit(YumConf.mdpolicy) 788 cost = IntOption(1000) 789 790 sslcacert = Inherit(YumConf.sslcacert) 791 sslverify = Inherit(YumConf.sslverify) 792 sslclientcert = Inherit(YumConf.sslclientcert) 793 sslclientkey = Inherit(YumConf.sslclientkey) 794 795 skip_if_unavailable = BoolOption(False)
796
797 -class VersionGroupConf(BaseConfig):
798 pkglist = ListOption() 799 run_with_packages = BoolOption(False)
800 801
802 -def readStartupConfig(configfile, root):
803 ''' 804 Parse Yum's main configuration file and return a StartupConf instance. 805 806 This is required in order to access configuration settings required as Yum 807 starts up. 808 809 @param configfile: The path to yum.conf. 810 @param root: The base path to use for installation (typically '/') 811 @return: A StartupConf instance. 812 813 May raise Errors.ConfigError if a problem is detected with while parsing. 814 ''' 815 816 # ' xemacs syntax hack 817 818 StartupConf.installroot.default = root 819 startupconf = StartupConf() 820 startupconf.config_file_path = configfile 821 parser = ConfigParser() 822 confpp_obj = ConfigPreProcessor(configfile) 823 try: 824 parser.readfp(confpp_obj) 825 except ParsingError, e: 826 raise Errors.ConfigError("Parsing file failed: %s" % e) 827 startupconf.populate(parser, 'main') 828 829 # Check that plugin paths are all absolute 830 for path in startupconf.pluginpath: 831 if not path[0] == '/': 832 raise Errors.ConfigError("All plugin search paths must be absolute") 833 # Stuff this here to avoid later re-parsing 834 startupconf._parser = parser 835 # setup the release ver here 836 startupconf.releasever = _getsysver(startupconf.installroot, startupconf.distroverpkg) 837 uuidfile = '%s/%s/uuid' % (startupconf.installroot, startupconf.persistdir) 838 startupconf.uuid = get_uuid(uuidfile) 839 840 return startupconf
841
842 -def readMainConfig(startupconf):
843 ''' 844 Parse Yum's main configuration file 845 846 @param startupconf: StartupConf instance as returned by readStartupConfig() 847 @return: Populated YumConf instance. 848 ''' 849 850 # ' xemacs syntax hack 851 852 # Set up substitution vars 853 yumvars = _getEnvVar() 854 yumvars['basearch'] = startupconf.basearch 855 yumvars['arch'] = startupconf.arch 856 yumvars['releasever'] = startupconf.releasever 857 yumvars['uuid'] = startupconf.uuid 858 859 # Read [main] section 860 yumconf = YumConf() 861 yumconf.populate(startupconf._parser, 'main') 862 863 # Apply the installroot to directory options 864 for option in ('cachedir', 'logfile', 'persistdir'): 865 path = getattr(yumconf, option) 866 ir_path = yumconf.installroot + path 867 ir_path = ir_path.replace('//', '/') # os.path.normpath won't fix this and 868 # it annoys me 869 ir_path = varReplace(ir_path, yumvars) 870 setattr(yumconf, option, ir_path) 871 872 # Add in some extra attributes which aren't actually configuration values 873 yumconf.yumvar = yumvars 874 yumconf.uid = 0 875 yumconf.cache = 0 876 yumconf.progess_obj = None 877 878 # items related to the originating config file 879 yumconf.config_file_path = startupconf.config_file_path 880 if os.path.exists(startupconf.config_file_path): 881 yumconf.config_file_age = os.stat(startupconf.config_file_path)[8] 882 else: 883 yumconf.config_file_age = 0 884 885 # propagate the debuglevel and errorlevel values: 886 yumconf.debuglevel = startupconf.debuglevel 887 yumconf.errorlevel = startupconf.errorlevel 888 889 return yumconf
890
891 -def readVersionGroupsConfig(configfile="/etc/yum/version-groups.conf"):
892 parser = ConfigParser() 893 confpp_obj = ConfigPreProcessor(configfile) 894 try: 895 parser.readfp(confpp_obj) 896 except ParsingError, e: 897 raise Errors.ConfigError("Parsing file failed: %s" % e) 898 ret = {} 899 for section in parser.sections(): 900 ret[section] = VersionGroupConf() 901 ret[section].populate(parser, section) 902 return ret
903 904
905 -def getOption(conf, section, name, option):
906 '''Convenience function to retrieve a parsed and converted value from a 907 ConfigParser. 908 909 @param conf: ConfigParser instance or similar 910 @param section: Section name 911 @param name: Option name 912 @param option: Option instance to use for conversion. 913 @return: The parsed value or default if value was not present. 914 915 Will raise ValueError if the option could not be parsed. 916 ''' 917 try: 918 val = conf.get(section, name) 919 except (NoSectionError, NoOptionError): 920 return option.default 921 return option.parse(val)
922
923 -def _getEnvVar():
924 '''Return variable replacements from the environment variables YUM0 to YUM9 925 926 The result is intended to be used with parser.varReplace() 927 ''' 928 yumvar = {} 929 for num in range(0, 10): 930 env = 'YUM%d' % num 931 val = os.environ.get(env, '') 932 if val: 933 yumvar[env.lower()] = val 934 return yumvar
935
936 -def _getsysver(installroot, distroverpkg):
937 '''Calculate the release version for the system. 938 939 @param installroot: The value of the installroot option. 940 @param distroverpkg: The value of the distroverpkg option. 941 @return: The release version as a string (eg. '4' for FC4) 942 ''' 943 ts = rpmUtils.transaction.initReadOnlyTransaction(root=installroot) 944 ts.pushVSFlags(~(rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS)) 945 try: 946 idx = ts.dbMatch('provides', distroverpkg) 947 except TypeError, e: 948 # This is code for "cannot open rpmdb" 949 # this is for pep 352 compliance on python 2.6 and above :( 950 if sys.hexversion < 0x02050000: 951 if hasattr(e,'message'): 952 raise Errors.YumBaseError("Error: " + str(e.message)) 953 else: 954 raise Errors.YumBaseError("Error: " + str(e)) 955 raise Errors.YumBaseError("Error: " + str(e)) 956 # we're going to take the first one - if there is more than one of these 957 # then the user needs a beating 958 if idx.count() == 0: 959 releasever = '$releasever' 960 else: 961 hdr = idx.next() 962 releasever = hdr['version'] 963 del hdr 964 del idx 965 del ts 966 return releasever
967
968 -def writeRawRepoFile(repo,only=None):
969 """ 970 Writes changes in a repo object back to a .repo file. 971 @param repo: Repo Object 972 @param only: List of attributes to work on (None = All) 973 It work by reading the repo file, changes the values there shall be changed and write it back to disk. 974 """ 975 976 if not _use_iniparse: 977 return 978 979 ini = INIConfig(open(repo.repofile)) 980 # Updated the ConfigParser with the changed values 981 cfgOptions = repo.cfg.options(repo.id) 982 for name,value in repo.iteritems(): 983 option = repo.optionobj(name) 984 if option.default != value or name in cfgOptions : 985 if only == None or name in only: 986 ini[repo.id][name] = option.tostring(value) 987 fp =file(repo.repofile,"w") 988 fp.write(str(ini)) 989 fp.close()
990 991 #def main(): 992 # mainconf = readMainConfig(readStartupConfig('/etc/yum/yum.conf', '/')) 993 # print mainconf.cachedir 994 # 995 #if __name__ == '__main__': 996 # main() 997