X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=source%2FBootServerRequest.py;h=9f7b07fcbc5d3948021d6d771aed41689d774859;hb=3a2a07818ad1b9a374a7ec78e8c4573a043dc338;hp=7b6531da33549dc6b147f10bf92045c3cd866c85;hpb=752736d288e356875e5a3198bf1ef1dd43ac9f34;p=bootmanager.git diff --git a/source/BootServerRequest.py b/source/BootServerRequest.py index 7b6531d..9f7b07f 100644 --- a/source/BootServerRequest.py +++ b/source/BootServerRequest.py @@ -8,19 +8,14 @@ from __future__ import print_function -import os, sys +import sys +import os import re import string import urllib import tempfile -# try to load pycurl -try: - import pycurl - PYCURL_LOADED = 1 -except: - PYCURL_LOADED = 0 - +import pycurl # if there is no cStringIO, fall back to the original try: @@ -32,8 +27,6 @@ except: class BootServerRequest: - VERBOSE = 0 - # all possible places to check the cdrom mount point. # /mnt/cdrom is typically after the machine has come up, # and /usr is when the boot cd is running @@ -55,13 +48,15 @@ class BootServerRequest: # really need for the boot cd environment where pycurl # doesn't exist CURL_CMD = 'curl' - CURL_SSL_VERSION = 3 + + # use TLSv1 and not SSLv3 anymore + CURL_SSL_VERSION = pycurl.SSLVERSION_TLSv1 def __init__(self, vars, verbose=0): self.VERBOSE = verbose self.VARS = vars - + # see if we have a boot cd mounted by checking for the version file # if HAS_BOOTCD == 0 then either the machine doesn't have # a boot cd, or something else is mounted @@ -71,12 +66,12 @@ class BootServerRequest: self.Message("Checking existance of boot cd on {}".format(path)) os.system("/bin/mount {} > /dev/null 2>&1".format(path)) - + version_file = self.VARS['BOOTCD_VERSION_FILE'].format(path=path) self.Message("Looking for version file {}".format(version_file)) if os.access(version_file, os.R_OK) == 0: - self.Message("No boot cd found."); + self.Message("No boot cd found.") else: self.Message("Found boot cd.") self.HAS_BOOTCD = 1 @@ -86,22 +81,22 @@ class BootServerRequest: # check the version of the boot cd, and locate the certs self.Message("Getting boot cd version.") - + versionRegExp = re.compile(r"PlanetLab BootCD v(\S+)") - + bootcd_version_f = file(version_file, "r") line = string.strip(bootcd_version_f.readline()) bootcd_version_f.close() - + match = versionRegExp.findall(line) if match: (self.BOOTCD_VERSION) = match[0] - + # right now, all the versions of the bootcd are supported, # so no need to check it - + self.Message("Getting server from configuration") - + bootservers = [ self.VARS['BOOT_SERVER'] ] for bootserver in bootservers: bootserver = string.strip(bootserver) @@ -134,7 +129,7 @@ class BootServerRequest: # see if we have any proxy info from the machine self.USE_PROXY = 0 self.Message("Checking existance of proxy config file...") - + if os.access(self.VARS['PROXY_FILE'], os.R_OK) and \ os.path.isfile(self.VARS['PROXY_FILE']): self.PROXY = string.strip(file(self.VARS['PROXY_FILE'], 'r').readline()) @@ -156,10 +151,10 @@ class BootServerRequest: self.Error(Msg) def MakeRequest(self, PartialPath, GetVars, - PostVars, DoSSL, DoCertCheck, - ConnectTimeout = DEFAULT_CURL_CONNECT_TIMEOUT, - MaxTransferTime = DEFAULT_CURL_MAX_TRANSFER_TIME, - FormData = None): + PostVars, DoSSL, DoCertCheck, + ConnectTimeout=DEFAULT_CURL_CONNECT_TIMEOUT, + MaxTransferTime=DEFAULT_CURL_MAX_TRANSFER_TIME, + FormData=None): fd, buffer_name = tempfile.mkstemp("MakeRequest-XXXXXX") os.close(fd) @@ -186,7 +181,7 @@ class BootServerRequest: os.unlink(buffer_name) except OSError: pass - + return ret def DownloadFile(self, PartialPath, GetVars, PostVars, @@ -202,10 +197,6 @@ class BootServerRequest: self.Error("No boot cd exists (needed to use -c and -s.\n") return 0 - if DoSSL and not PYCURL_LOADED: - self.Warning("Using SSL without pycurl will by default " \ - "check at least standard certs.") - # ConnectTimeout has to be greater than 0 if ConnectTimeout <= 0: self.Error("Connect timeout must be greater than zero.\n") @@ -221,7 +212,7 @@ class BootServerRequest: dopostdata = 1 postdata = urllib.urlencode(PostVars) self.Message("Posting data:\n{}\n".format(postdata)) - + getstr = "" if GetVars: getstr = "?" + urllib.urlencode(GetVars) @@ -233,21 +224,21 @@ class BootServerRequest: cert_list = self.MONITORSERVER_CERTS else: cert_list = self.BOOTSERVER_CERTS - + for server in cert_list: self.Message("Contacting server {}.".format(server)) - + certpath = cert_list[server] - + # output what we are going to be doing self.Message("Connect timeout is {} seconds".format(ConnectTimeout)) self.Message("Max transfer time is {} seconds".format(MaxTransferTime)) if DoSSL: url = "https://{}/{}{}".format(server, PartialPath, getstr) - - if DoCertCheck and PYCURL_LOADED: + + if DoCertCheck: self.Message("Using SSL version {} and verifying peer." .format(self.CURL_SSL_VERSION)) else: @@ -255,139 +246,77 @@ class BootServerRequest: .format(self.CURL_SSL_VERSION)) else: url = "http://{}/{}{}".format(server, PartialPath, getstr) - + self.Message("URL: {}".format(url)) - - # setup a new pycurl instance, or a curl command line string - # if we don't have pycurl - - if PYCURL_LOADED: - curl = pycurl.Curl() - - # don't want curl sending any signals - curl.setopt(pycurl.NOSIGNAL, 1) - - curl.setopt(pycurl.CONNECTTIMEOUT, ConnectTimeout) - curl.setopt(pycurl.TIMEOUT, MaxTransferTime) - - # do not follow location when attempting to download a file - curl.setopt(pycurl.FOLLOWLOCATION, 0) - - if self.USE_PROXY: - curl.setopt(pycurl.PROXY, self.PROXY) - - if DoSSL: - curl.setopt(pycurl.SSLVERSION, self.CURL_SSL_VERSION) - - if DoCertCheck: - curl.setopt(pycurl.CAINFO, certpath) - curl.setopt(pycurl.SSL_VERIFYPEER, 2) - - else: - curl.setopt(pycurl.SSL_VERIFYPEER, 0) - - if dopostdata: - curl.setopt(pycurl.POSTFIELDS, postdata) - - # setup multipart/form-data upload - if FormData: - curl.setopt(pycurl.HTTPPOST, FormData) - - curl.setopt(pycurl.URL, url) - else: - cmdline = "{} " \ - "--connect-timeout {} " \ - "--max-time {} " \ - "--header Pragma: " \ - "--output {} " \ - "--fail "\ - .format(self.CURL_CMD, ConnectTimeout, - MaxTransferTime, DestFilePath) - - if dopostdata: - cmdline = cmdline + "--data '" + postdata + "' " - - if FormData: - cmdline = cmdline + "".join(["--form '" + field + "' " for field in FormData]) - - if not self.VERBOSE: - cmdline = cmdline + "--silent " - - if self.USE_PROXY: - cmdline = cmdline + "--proxy {} ".format(self.PROXY) - - if DoSSL: - cmdline = cmdline + "--sslv{} ".format(self.CURL_SSL_VERSION) - if DoCertCheck: - cmdline = cmdline + "--cacert {} ".format(certpath) - - cmdline = cmdline + url - - self.Message("curl command: {}".format(cmdline)) - - - if PYCURL_LOADED: - try: - # setup the output file - outfile = open(DestFilePath,"wb") - + # setup a new pycurl instance + curl = pycurl.Curl() + + # don't want curl sending any signals + curl.setopt(pycurl.NOSIGNAL, 1) + + curl.setopt(pycurl.CONNECTTIMEOUT, ConnectTimeout) + curl.setopt(pycurl.TIMEOUT, MaxTransferTime) + + # do not follow location when attempting to download a file + curl.setopt(pycurl.FOLLOWLOCATION, 0) + + if self.USE_PROXY: + curl.setopt(pycurl.PROXY, self.PROXY) + + if DoSSL: + curl.setopt(pycurl.SSLVERSION, self.CURL_SSL_VERSION) + + if DoCertCheck: + curl.setopt(pycurl.CAINFO, certpath) + curl.setopt(pycurl.SSL_VERIFYPEER, 2) + else: + curl.setopt(pycurl.SSL_VERIFYPEER, 0) + + if dopostdata: + curl.setopt(pycurl.POSTFIELDS, postdata) + + # setup multipart/form-data upload + if FormData: + curl.setopt(pycurl.HTTPPOST, FormData) + + curl.setopt(pycurl.URL, url) + + try: + # setup the output file + with open(DestFilePath, "wb") as outfile: + self.Message("Opened output file {}".format(DestFilePath)) - + curl.setopt(pycurl.WRITEDATA, outfile) - + self.Message("Fetching...") curl.perform() self.Message("Done.") - + http_result = curl.getinfo(pycurl.HTTP_CODE) curl.close() - - outfile.close() - self.Message("Results saved in {}".format(DestFilePath)) - - # check the code, return 1 if successfull - if http_result == self.HTTP_SUCCESS: - self.Message("Successfull!") - return 1 - else: - self.Message("Failure, resultant http code: {}" - .format(http_result)) - - except pycurl.error as err: - errno, errstr = err - self.Error("connect to {} failed; curl error {}: '{}'\n" - .format(server, errno, errstr)) - - if not outfile.closed: - try: - os.unlink(DestFilePath) - outfile.close() - except OSError: - pass - else: - self.Message("Fetching...") - rc = os.system(cmdline) - self.Message("Done.") - - if rc != 0: - try: - os.unlink(DestFilePath) - except OSError: - pass - self.Message("Failure, resultant curl code: {}".format(rc)) - self.Message("Removed {}".format(DestFilePath)) - else: + self.Message("Results saved in {}".format(DestFilePath)) + + # check the code, return 1 if successfull + if http_result == self.HTTP_SUCCESS: self.Message("Successfull!") return 1 - + else: + self.Message("Failure, resultant http code: {}" + .format(http_result)) + + except pycurl.error as err: + errno, errstr = err + self.Error("connect to {} failed; curl error {}: '{}'\n" + .format(server, errno, errstr)) + self.Error("Unable to successfully contact any boot servers.\n") return 0 - def usage(): print( """ @@ -398,13 +327,13 @@ Options: -o/--output Write result to file -s/--ssl Make the request over HTTPS -v Makes the operation more talkative -"""); +"""); if __name__ == "__main__": import getopt - + # check out our command line options try: opt_list, arg_list = getopt.getopt(sys.argv[1:], @@ -416,15 +345,15 @@ if __name__ == "__main__": checkcert = 0 output_file = None verbose = 0 - + for opt, arg in opt_list: if opt in ("-h","--help"): usage(0) sys.exit() - + if opt in ("-c","--checkcert"): checkcert = 1 - + if opt in ("-s","--ssl"): ssl = 1 @@ -433,7 +362,7 @@ if __name__ == "__main__": if opt == "-v": verbose = 1 - + if len(arg_list) != 1: raise Exception @@ -447,10 +376,10 @@ if __name__ == "__main__": # got the command line args straightened out requestor = BootServerRequest(verbose) - + if output_file: requestor.DownloadFile(partialpath, None, None, ssl, - checkcert, output_file) + checkcert, output_file) else: result = requestor.MakeRequest(partialpath, None, None, ssl, checkcert) if result: