Package up2date_client :: Module capabilities
[hide private]
[frames] | no frames]

Source Code for Module up2date_client.capabilities

  1   
  2  from up2date_client import config 
  3  from up2date_client import up2dateErrors 
  4   
  5  try: # python2 
  6      import UserDict 
  7  except ImportError: # python3 
  8      import collections as UserDict 
  9   
 10  import gettext 
 11  t = gettext.translation('rhn-client-tools', fallback=True) 
 12  # Python 3 translations don't have a ugettext method 
 13  if not hasattr(t, 'ugettext'): 
 14      t.ugettext = t.gettext 
 15  _ = t.ugettext 
 16   
 17  # a dict with "capability name" as the key, and the version 
 18  # as the value. 
 19  neededCaps = {"caneatCheese": {'version':"21"}, 
 20                "supportsAutoUp2dateOption": {'version': "1"}, 
 21                "registration.finish_message": {'version': "1"}, 
 22                "xmlrpc.packages.extended_profile": {'version':"1"}, 
 23                "registration.delta_packages": {'version':"1"}, 
 24                "registration.update_contact_info": {'version': "1"}, 
 25                "registration.extended_update_support": {"version" : "1"}, 
 26                "registration.smbios": {"version" : "1"}} 
 27   
28 -def parseCap(capstring):
29 value = None 30 caps = capstring.split(',') 31 32 capslist = [] 33 for cap in caps: 34 try: 35 (key_version, value) = [i.strip() for i in cap.split("=", 1)] 36 except ValueError: 37 # Bad directive: not in 'a = b' format 38 continue 39 40 # parse out the version 41 # lets give it a shot sans regex's first... 42 (key,version) = key_version.split("(", 1) 43 44 # just to be paranoid 45 if version[-1] != ")": 46 print("something broke in parsing the capabilited headers") 47 #FIXME: raise an approriate exception here... 48 49 # trim off the trailing paren 50 version = version[:-1] 51 data = {'version': version, 'value': value} 52 53 capslist.append((key, data)) 54 55 return capslist
56
57 -class Capabilities(UserDict.UserDict):
58 - def __init__(self):
59 UserDict.UserDict.__init__(self) 60 self.missingCaps = {} 61 #self.populate() 62 # self.validate() 63 self.neededCaps = neededCaps 64 self.cfg = config.initUp2dateConfig()
65 66
67 - def populate(self, headers):
68 for key, val in headers.items(): 69 if key.lower() == "x-rhn-server-capability": 70 capslist = parseCap(val) 71 72 for (cap,data) in capslist: 73 self.data[cap] = data
74
75 - def parseCapVersion(self, versionString):
76 index = versionString.find('-') 77 # version of "-" is bogus, ditto for "1-" 78 if index > 0: 79 rng = versionString.split("-") 80 start = rng[0] 81 end = rng[1] 82 versions = range(int(start), int(end)+1) 83 return versions 84 85 vers = versionString.split(':') 86 if len(vers) > 1: 87 versions = [int(a) for a in vers] 88 return versions 89 90 return [int(versionString)]
91
92 - def validateCap(self, cap, capvalue):
93 if not cap in self.data: 94 errstr = _("This client requires the server to support %s, which the current " \ 95 "server does not support") % cap 96 self.missingCaps[cap] = None 97 else: 98 data = self.data[cap] 99 # DOES the server have the version we need 100 if int(capvalue['version']) not in self.parseCapVersion(data['version']): 101 self.missingCaps[cap] = self.neededCaps[cap]
102 103
104 - def validate(self):
105 for key in self.neededCaps.keys(): 106 self.validateCap(key, self.neededCaps[key]) 107 108 self.workaroundMissingCaps()
109
110 - def setConfig(self, key, configItem):
111 if key in self.tmpCaps: 112 self.cfg[configItem] = 0 113 del self.tmpCaps[key] 114 else: 115 self.cfg[configItem] = 1
116
117 - def workaroundMissingCaps(self):
118 # if we have caps that we know we want, but we can 119 # can work around, setup config variables here so 120 # that we know to do just that 121 self.tmpCaps = self.missingCaps 122 123 # this is an example of how to work around it 124 key = 'caneatCheese' 125 if key in self.tmpCaps: 126 # do whatevers needed to workaround 127 del self.tmpCaps[key] 128 else: 129 # we support this, set a config option to 130 # indicate that possibly 131 pass 132 133 # dict of key to configItem, and the config item that 134 # corresponds with it 135 136 capsConfigMap = {'supportsAutoUp2dateOption': 'supportsAutoUp2dateOption', 137 'registration.finish_message': 'supportsFinishMessage', 138 "registration.update_contact_info" : 'supportsUpdateContactInfo', 139 "registration.delta_packages" : 'supportsDeltaPackages', 140 "xmlrpc.packages.extended_profile" : 'supportsExtendedPackageProfile', 141 "registration.extended_update_support" : "supportsEUS", 142 "registration.smbios" : "supportsSMBIOS"} 143 144 for key in capsConfigMap.keys(): 145 self.setConfig(key, capsConfigMap[key]) 146 147 # if we want to blow up on missing caps we cant eat around 148 missingCaps = [] 149 wrongVersionCaps = [] 150 151 if len(self.tmpCaps): 152 for cap in self.tmpCaps: 153 capInfo = self.tmpCaps[cap] 154 if capInfo == None: 155 # it's completly mssing 156 missingCaps.append((cap, capInfo)) 157 else: 158 wrongVersionCaps.append((cap, capInfo)) 159 160 errString = "" 161 errorList = [] 162 if len(wrongVersionCaps): 163 for (cap, capInfo) in wrongVersionCaps: 164 errString = errString + "Needs %s of version: %s but server has version: %s\n" % (cap, 165 capInfo['version'], 166 self.data[cap]['version']) 167 errorList.append({"capName":cap, "capInfo":capInfo, "serverVersion":self.data[cap]}) 168 169 if len(missingCaps): 170 for (cap, capInfo) in missingCaps: 171 errString = errString + "Needs %s but server does not support that capability\n" % (cap) 172 errorList.append({"capName":cap, "capInfo":capInfo, "serverVersion":""}) 173 174 if len(errString): 175 raise up2dateErrors.ServerCapabilityError(errString, errorList)
176
177 - def hasCapability(self, capability, version=None):
178 """Checks if the server supports a capability and optionally a version. 179 Returns True or False. 180 181 This complements the neededCaps mechanism provided by this module. 182 Using hasCapability makes it easier to do something only if the server 183 supports it or to put workaround code in the user of this class. The 184 neededCaps mechanism makes it easier to put workaround code in this 185 module, which makes sense if it is to be shared. 186 187 'capability' should be a string such as 'registration.foobar'. It can 188 be a capability in 'neededCaps' above or one that isn't there. 'version' 189 can be a string (where isdigit() is True) or an int. 190 191 """ 192 assert version is None or str(version).isdigit() 193 194 if not capability in self.data: 195 return False 196 if version: 197 data = self.data[capability] 198 if int(version) not in self.parseCapVersion(data['version']): 199 return False 200 return True
201