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

Source Code for Module up2date_client.rpcServer

  1  # 
  2   
  3  import os 
  4  import sys 
  5  import socket 
  6  import time 
  7   
  8  from up2date_client import config 
  9  from up2date_client import clientCaps 
 10  from up2date_client import up2dateLog 
 11  from up2date_client import up2dateErrors 
 12  from up2date_client import up2dateUtils 
 13   
 14  from rhn import SSL 
 15  from rhn import rpclib 
 16  from rhn.tb import raise_with_tb 
 17   
 18  try: # python2 
 19       import httplib 
 20       import urllib2 
 21       import urlparse 
 22       import xmlrpclib 
 23  except ImportError: # python3 
 24       import http.client as httplib 
 25       import urllib.request as urllib2 
 26       import urllib.parse as urlparse 
 27       import xmlrpc.client as xmlrpclib 
 28   
 29  import gettext 
 30  t = gettext.translation('rhn-client-tools', fallback=True) 
 31  # Python 3 translations don't have a ugettext method 
 32  if not hasattr(t, 'ugettext'): 
 33      t.ugettext = t.gettext 
 34  _ = t.ugettext 
 35   
36 -def stdoutMsgCallback(msg):
37 print(msg)
38 39
40 -class RetryServer(rpclib.Server):
41 - def addServerList(self, serverList):
42 self.serverList = serverList
43
44 - def _request1(self, methodname, params):
45 self.log = up2dateLog.initLog() 46 while 1: 47 try: 48 ret = self._request(methodname, params) 49 except rpclib.InvalidRedirectionError: 50 raise 51 except xmlrpclib.Fault: 52 raise 53 except httplib.BadStatusLine: 54 self.log.log_me("Error: Server Unavailable. Please try later.") 55 stdoutMsgCallback( 56 _("Error: Server Unavailable. Please try later.")) 57 sys.exit(-1) 58 except: 59 server = self.serverList.next() 60 if server == None: 61 # since just because we failed, the server list could 62 # change (aka, firstboot, they get an option to reset the 63 # the server configuration) so reset the serverList 64 self.serverList.resetServerIndex() 65 raise 66 67 msg = "An error occurred talking to %s:\n" % self._host 68 msg = msg + "%s\n%s\n" % (sys.exc_info()[0], sys.exc_info()[1]) 69 msg = msg + "Trying the next serverURL: %s\n" % self.serverList.server() 70 self.log.log_me(msg) 71 # try a different url 72 73 # use the next serverURL 74 parse_res = urlparse.urlsplit(self.serverList.server()) 75 typ = parse_res[0] # scheme 76 self._host = parse_res[1] # netloc 77 self._handler = parse_res[2] # path 78 typ = typ.lower() 79 if typ not in ("http", "https"): 80 raise_with_tb(rpclib.InvalidRedirectionError( 81 "Redirected to unsupported protocol %s" % typ)) 82 self._orig_handler = self._handler 83 self._type = typ 84 self._uri = self.serverList.server() 85 if not self._handler: 86 self._handler = "/RPC2" 87 self._allow_redirect = 1 88 continue 89 # if we get this far, we succedded 90 break 91 return ret
92 93
94 - def __getattr__(self, name):
95 # magic method dispatcher 96 return rpclib.xmlrpclib._Method(self._request1, name)
97 98 99 # uh, yeah, this could be an iterator, but we need it to work on 1.5 as well
100 -class ServerList:
101 - def __init__(self, serverlist=[]):
102 self.serverList = serverlist 103 self.index = 0
104
105 - def server(self):
106 self.serverurl = self.serverList[self.index] 107 return self.serverurl
108 109
110 - def next(self):
111 self.index = self.index + 1 112 if self.index >= len(self.serverList): 113 return None 114 return self.server()
115
116 - def resetServerIndex(self):
117 self.index = 0
118 119
120 -def getServer(refreshCallback=None, serverOverride=None, timeout=None):
121 log = up2dateLog.initLog() 122 cfg = config.initUp2dateConfig() 123 124 # Where do we keep the CA certificate for RHNS? 125 # The servers we're talking to need to have their certs 126 # signed by one of these CA. 127 ca = cfg["sslCACert"] 128 if not isinstance(ca, list): 129 ca = [ca] 130 131 rhns_ca_certs = ca or ["/usr/share/rhn/RHNS-CA-CERT"] 132 if cfg["enableProxy"]: 133 proxyHost = config.getProxySetting() 134 else: 135 proxyHost = None 136 137 if not serverOverride: 138 serverUrls = config.getServerlURL() 139 else: 140 serverUrls = serverOverride 141 serverList = ServerList(serverUrls) 142 143 proxyUser = None 144 proxyPassword = None 145 if cfg["enableProxyAuth"]: 146 proxyUser = cfg["proxyUser"] or None 147 proxyPassword = cfg["proxyPassword"] or None 148 149 lang = None 150 for env in 'LANGUAGE', 'LC_ALL', 'LC_MESSAGES', 'LANG': 151 if env in os.environ: 152 if not os.environ[env]: 153 # sometimes unset 154 continue 155 lang = os.environ[env].split(':')[0] 156 lang = lang.split('.')[0] 157 break 158 159 160 s = RetryServer(serverList.server(), 161 refreshCallback=refreshCallback, 162 proxy=proxyHost, 163 username=proxyUser, 164 password=proxyPassword, 165 timeout=timeout) 166 s.addServerList(serverList) 167 168 s.add_header("X-Up2date-Version", up2dateUtils.version()) 169 170 if lang: 171 s.setlang(lang) 172 173 # require RHNS-CA-CERT file to be able to authenticate the SSL connections 174 need_ca = [ True for i in s.serverList.serverList 175 if urlparse.urlparse(i)[0] == 'https'] 176 if need_ca: 177 for rhns_ca_cert in rhns_ca_certs: 178 if not os.access(rhns_ca_cert, os.R_OK): 179 msg = "%s: %s" % (_("ERROR: can not find RHNS CA file"), 180 rhns_ca_cert) 181 log.log_me("%s" % msg) 182 raise up2dateErrors.SSLCertificateFileNotFound(msg) 183 184 # force the validation of the SSL cert 185 s.add_trusted_cert(rhns_ca_cert) 186 187 clientCaps.loadLocalCaps() 188 189 # send up the capabality info 190 headerlist = clientCaps.caps.headerFormat() 191 for (headerName, value) in headerlist: 192 s.add_header(headerName, value) 193 return s
194 195
196 -def doCall(method, *args, **kwargs):
197 log = up2dateLog.initLog() 198 log.log_debug("rpcServer: Calling XMLRPC %s" % method.__dict__['_Method__name']) 199 cfg = config.initUp2dateConfig() 200 ret = None 201 202 attempt_count = 1 203 try: 204 attempts = int(cfg["networkRetries"]) 205 except ValueError: 206 attempts = 1 207 if attempts <= 0: 208 attempts = 1 209 210 while 1: 211 failure = 0 212 ret = None 213 try: 214 ret = method(*args, **kwargs) 215 except KeyboardInterrupt: 216 raise_with_tb(up2dateErrors.CommunicationError(_( 217 "Connection aborted by the user"))) 218 # if we get a socket error, keep tryingx2 219 except (socket.error, SSL.socket_error): 220 log.log_me("A socket error occurred: %s, attempt #%s" % ( 221 sys.exc_info()[1], attempt_count)) 222 if attempt_count >= attempts: 223 e = sys.exc_info()[1] 224 if len(e.args) > 1: 225 raise_with_tb(up2dateErrors.CommunicationError(e.args[1])) 226 else: 227 raise_with_tb(up2dateErrors.CommunicationError(e.args[0])) 228 else: 229 failure = 1 230 except httplib.IncompleteRead: 231 print("httplib.IncompleteRead") 232 raise_with_tb(up2dateErrors.CommunicationError("httplib.IncompleteRead")) 233 234 except urllib2.HTTPError: 235 e = sys.exc_info()[1] 236 msg = "\nAn HTTP error occurred:\n" 237 msg = msg + "URL: %s\n" % e.filename 238 msg = msg + "Status Code: %s\n" % e.code 239 msg = msg + "Error Message: %s\n" % e.msg 240 log.log_me(msg) 241 raise_with_tb(up2dateErrors.CommunicationError(msg)) 242 243 except xmlrpclib.ProtocolError: 244 e = sys.exc_info()[1] 245 log.log_me("A protocol error occurred: %s , attempt #%s," % ( 246 e.errmsg, attempt_count)) 247 if e.errcode == 404: 248 log.log_me("Could not find URL, %s" % (e.url)) 249 log.log_me("Check server name and/or URL, then retry\n"); 250 251 (errCode, errMsg) = rpclib.reportError(e.headers) 252 reset = 0 253 if abs(errCode) == 34: 254 log.log_me("Auth token timeout occurred\n errmsg: %s" % errMsg) 255 # this calls login, which in tern calls doCall (ie, 256 # this function) but login should never get a 34, so 257 # should be safe from recursion 258 259 from up2date_client import up2dateAuth 260 up2dateAuth.updateLoginInfo() 261 262 # the servers are being throttle to pay users only, catch the 263 # exceptions and display a nice error message 264 if abs(errCode) == 51: 265 log.log_me(_("Server has refused connection due to high load")) 266 raise_with_tb(up2dateErrors.CommunicationError(e.errmsg)) 267 # if we get a 404 from our server, thats pretty 268 # fatal... no point in retrying over and over. Note that 269 # errCode == 17 is specific to our servers, if the 270 # serverURL is just pointing somewhere random they will 271 # get a 0 for errcode and will raise a CommunicationError 272 if abs(errCode) == 17: 273 #in this case, the args are the package string, so lets try to 274 # build a useful error message 275 if type(args[0]) == type([]): 276 pkg = args[0] 277 else: 278 pkg=args[1] 279 280 if type(pkg) == type([]): 281 pkgName = "%s-%s-%s.%s" % (pkg[0], pkg[1], pkg[2], pkg[4]) 282 else: 283 pkgName = pkg 284 msg = "File Not Found: %s\n%s" % (pkgName, errMsg) 285 log.log_me(msg) 286 raise_with_tb(up2dateErrors.FileNotFoundError(msg)) 287 288 if not reset: 289 if attempt_count >= attempts: 290 raise_with_tb(up2dateErrors.CommunicationError(e.errmsg)) 291 else: 292 failure = 1 293 294 except xmlrpclib.ResponseError: 295 raise_with_tb(up2dateErrors.CommunicationError( 296 "Broken response from the server.")) 297 298 if ret != None: 299 break 300 else: 301 failure = 1 302 303 304 if failure: 305 # rest for five seconds before trying again 306 time.sleep(5) 307 attempt_count = attempt_count + 1 308 309 if attempt_count > attempts: 310 raise up2dateErrors.CommunicationError("The data returned from the server was incomplete") 311 312 return ret
313