X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=source%2FBootServerRequest.py;h=7b6531da33549dc6b147f10bf92045c3cd866c85;hb=752736d288e356875e5a3198bf1ef1dd43ac9f34;hp=f37b2cedd3cdbf0f1c1e130ef9231d1beec58e4e;hpb=7ab7e9dd797333a9fdc8604554e16e192a32144d;p=bootmanager.git diff --git a/source/BootServerRequest.py b/source/BootServerRequest.py index f37b2ce..7b6531d 100644 --- a/source/BootServerRequest.py +++ b/source/BootServerRequest.py @@ -1,58 +1,25 @@ -#!/usr/bin/python2 - +#!/usr/bin/python +# # Copyright (c) 2003 Intel Corporation # All rights reserved. +# +# Copyright (c) 2004-2006 The Trustees of Princeton University +# All rights reserved. -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: - -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. - -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. - -# * Neither the name of the Intel Corporation nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. - -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF -# YOUR JURISDICTION. It is licensee's responsibility to comply with any -# export regulations applicable in licensee's jurisdiction. Under -# CURRENT (May 2000) U.S. export regulations this software is eligible -# for export from the U.S. and can be downloaded by or otherwise -# exported or reexported worldwide EXCEPT to U.S. embargoed destinations -# which include Cuba, Iraq, Libya, North Korea, Iran, Syria, Sudan, -# Afghanistan and any other country to which the U.S. has embargoed -# goods and services. - +from __future__ import print_function import os, sys import re import string import urllib +import tempfile # try to load pycurl try: import pycurl - PYCURL_LOADED= 1 + PYCURL_LOADED = 1 except: - PYCURL_LOADED= 0 + PYCURL_LOADED = 0 # if there is no cStringIO, fall back to the original @@ -70,47 +37,30 @@ class BootServerRequest: # 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 - CDROM_MOUNT_PATH = ("/mnt/cdrom/","/usr/") - - # this is the server to contact if we don't have a bootcd - DEFAULT_BOOT_SERVER = "boot.planet-lab.org" - - BOOTCD_VERSION_FILE = "bootme/ID" - BOOTCD_SERVER_FILE = "bootme/BOOTSERVER" - BOOTCD_SERVER_CERT_DIR = "bootme/cacert" - CACERT_NAME = "cacert.pem" - - # location of file containing http/https proxy info, if needed - PROXY_FILE = '/etc/planetlab/http_proxy' + CDROM_MOUNT_PATH = ("/mnt/cdrom/", "/usr/") + BOOTSERVER_CERTS = {} + MONITORSERVER_CERTS = {} + BOOTCD_VERSION = "" + HTTP_SUCCESS = 200 + HAS_BOOTCD = 0 + USE_PROXY = 0 + PROXY = 0 + # in seconds, how maximum time allowed for connect + DEFAULT_CURL_CONNECT_TIMEOUT = 30 + # in seconds, maximum time allowed for any transfer + DEFAULT_CURL_MAX_TRANSFER_TIME = 3600 # location of curl executable, if pycurl isn't available # and the DownloadFile method is called (backup, only # really need for the boot cd environment where pycurl # doesn't exist CURL_CMD = 'curl' - - # in seconds, how maximum time allowed for connect - DEFAULT_CURL_CONNECT_TIMEOUT = 30 - - # in seconds, maximum time allowed for any transfer - DEFAULT_CURL_MAX_TRANSFER_TIME = 3600 - CURL_SSL_VERSION = 3 - HTTP_SUCCESS = 200 - - # proxy variables - USE_PROXY = 0 - PROXY = 0 + def __init__(self, vars, verbose=0): - # bootcd variables - HAS_BOOTCD = 0 - BOOTCD_VERSION = "" - BOOTSERVER_CERTS= {} - - def __init__(self, verbose=0): - - self.VERBOSE= verbose + 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 @@ -118,286 +68,201 @@ class BootServerRequest: self.HAS_BOOTCD = 0 for path in self.CDROM_MOUNT_PATH: - self.Message( "Checking existance of boot cd on %s" % path ) + self.Message("Checking existance of boot cd on {}".format(path)) - os.system("/bin/mount %s > /dev/null 2>&1" % path ) + os.system("/bin/mount {} > /dev/null 2>&1".format(path)) - version_file= path + self.BOOTCD_VERSION_FILE - self.Message( "Looking for version file %s" % version_file ) + 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 + self.Message("Found boot cd.") + self.HAS_BOOTCD = 1 break - if self.HAS_BOOTCD: # check the version of the boot cd, and locate the certs - self.Message( "Getting boot cd version." ) + self.Message("Getting boot cd version.") - versionRegExp= re.compile(r"PlanetLab BootCD v(\S+)") + 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 = file(version_file, "r") + line = string.strip(bootcd_version_f.readline()) bootcd_version_f.close() - match= versionRegExp.findall(line) + match = versionRegExp.findall(line) if match: - (self.BOOTCD_VERSION)= match[0] + (self.BOOTCD_VERSION) = match[0] # right now, all the versions of the bootcd are supported, # so no need to check it - # create a list of the servers we should - # attempt to contact, and the certs for each - server_list= path + self.BOOTCD_SERVER_FILE - self.Message( "Getting list of servers off of cd from %s." % - server_list ) - - bootservers_f= file(server_list,"r") - bootservers= bootservers_f.readlines() - bootservers_f.close() + self.Message("Getting server from configuration") + bootservers = [ self.VARS['BOOT_SERVER'] ] for bootserver in bootservers: bootserver = string.strip(bootserver) - cacert_path= "%s/%s/%s/%s" % \ - (path,self.BOOTCD_SERVER_CERT_DIR, - bootserver,self.CACERT_NAME) + cacert_path = "{}/{}/{}".format( + self.VARS['SERVER_CERT_DIR'].format(path=path), + bootserver, + self.VARS['CACERT_NAME']) + if os.access(cacert_path, os.R_OK): + self.BOOTSERVER_CERTS[bootserver] = cacert_path + + monitorservers = [ self.VARS['MONITOR_SERVER'] ] + for monitorserver in monitorservers: + monitorserver = string.strip(monitorserver) + cacert_path = "{}/{}/{}".format( + self.VARS['SERVER_CERT_DIR'].format(path=path), + monitorserver, + self.VARS['CACERT_NAME']) if os.access(cacert_path, os.R_OK): - self.BOOTSERVER_CERTS[bootserver]= cacert_path + self.MONITORSERVER_CERTS[monitorserver] = cacert_path - self.Message( "Set of servers to contact: %s" % - str(self.BOOTSERVER_CERTS) ) + self.Message("Set of servers to contact: {}".format(self.BOOTSERVER_CERTS)) + self.Message("Set of servers to upload to: {}".format(self.MONITORSERVER_CERTS)) else: - self.Message( "Using default boot server address." ) - self.BOOTSERVER_CERTS[self.DEFAULT_BOOT_SERVER]= "" + self.Message("Using default boot server address.") + self.BOOTSERVER_CERTS[self.VARS['DEFAULT_BOOT_SERVER']] = "" + self.MONITORSERVER_CERTS[self.VARS['DEFAULT_BOOT_SERVER']] = "" - def CheckProxy( self ): + def CheckProxy(self): # see if we have any proxy info from the machine - self.USE_PROXY= 0 - self.Message( "Checking existance of proxy config file..." ) + self.USE_PROXY = 0 + self.Message("Checking existance of proxy config file...") - if os.access(self.PROXY_FILE, os.R_OK) and \ - os.path.isfile(self.PROXY_FILE): - self.PROXY= string.strip(file(self.PROXY_FILE,'r').readline()) - self.USE_PROXY= 1 - self.Message( "Using proxy %s." % self.PROXY ) + 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()) + self.USE_PROXY = 1 + self.Message("Using proxy {}.".format(self.PROXY)) else: - self.Message( "Not using any proxy." ) + self.Message("Not using any proxy.") - def Message( self, Msg ): - if( self.VERBOSE ): - print( Msg ) + def Message(self, Msg): + if(self.VERBOSE): + print(Msg) + def Error(self, Msg): + sys.stderr.write(Msg + "\n") - - def Error( self, Msg ): - sys.stderr.write( Msg + "\n" ) - - - - def Warning( self, Msg ): + def Warning(self, Msg): self.Error(Msg) - - - def MakeRequest( self, PartialPath, GetVars, + def MakeRequest(self, PartialPath, GetVars, PostVars, DoSSL, DoCertCheck, - ConnectTimeout= DEFAULT_CURL_CONNECT_TIMEOUT, - MaxTransferTime= DEFAULT_CURL_MAX_TRANSFER_TIME): - - if PYCURL_LOADED == 0: - self.Error( "MakeRequest method requires pycurl." ) - return None - - self.CheckProxy() - - self.Message( "Attempting to retrieve %s" % PartialPath ) - - # we can't do ssl and check the cert if we don't have a bootcd - if DoSSL and DoCertCheck and not self.HAS_BOOTCD: - self.Error( "No boot cd exists (needed to use -c and -s.\n" ) - return None - - # didn't pass a path in? just get the root doc - if PartialPath == "": - PartialPath= "/" - - # ConnectTimeout has to be greater than 0 - if ConnectTimeout <= 0: - self.Error( "Connect timeout must be greater than zero.\n" ) - return None - - # setup the post and get vars for the request - if PostVars: - dopostdata= 1 - postdata = urllib.urlencode(PostVars) - self.Message( "Posting data:\n%s\n" % postdata ) + ConnectTimeout = DEFAULT_CURL_CONNECT_TIMEOUT, + MaxTransferTime = DEFAULT_CURL_MAX_TRANSFER_TIME, + FormData = None): + + fd, buffer_name = tempfile.mkstemp("MakeRequest-XXXXXX") + os.close(fd) + buffer = open(buffer_name, "w+b") + + # the file "buffer_name" will be deleted by DownloadFile() + + ok = self.DownloadFile(PartialPath, GetVars, PostVars, + DoSSL, DoCertCheck, buffer_name, + ConnectTimeout, + MaxTransferTime, + FormData) + + # check the ok code, return the string only if it was successfull + if ok: + buffer.seek(0) + ret = buffer.read() else: - dopostdata= 0 - - getstr= "" - if GetVars: - getstr= "?" + urllib.urlencode(GetVars) - self.Message( "Get data:\n%s\n" % getstr ) - - # now, attempt to make the request, starting at the first - # server in the list - for server in self.BOOTSERVER_CERTS: - self.Message( "Contacting server %s." % server ) - - certpath = self.BOOTSERVER_CERTS[server] - - curl= pycurl.Curl() - - # don't want curl sending any signals - curl.setopt(pycurl.NOSIGNAL, 1) - - curl.setopt(pycurl.CONNECTTIMEOUT, ConnectTimeout) - self.Message( "Connect timeout is %s seconds" % \ - ConnectTimeout ) - - curl.setopt(pycurl.TIMEOUT, MaxTransferTime) - self.Message( "Max transfer time is %s seconds" % \ - MaxTransferTime ) + ret = None + + buffer.close() + try: + # just in case it is not deleted by DownloadFile() + os.unlink(buffer_name) + except OSError: + pass - curl.setopt(pycurl.FOLLOWLOCATION, 1) - curl.setopt(pycurl.MAXREDIRS, 2) - - if self.USE_PROXY: - curl.setopt(pycurl.PROXY, self.PROXY ) - - if DoSSL: - curl.setopt(pycurl.SSLVERSION, self.CURL_SSL_VERSION) - - url = "https://%s/%s%s" % (server,PartialPath,getstr) - if DoCertCheck: - curl.setopt(pycurl.CAINFO, certpath) - curl.setopt(pycurl.SSL_VERIFYPEER, 2) - self.Message( "Using SSL version %d and verifying peer." % \ - self.CURL_SSL_VERSION ) - else: - curl.setopt(pycurl.SSL_VERIFYPEER, 0) - self.Message( "Using SSL version %d" % \ - self.CURL_SSL_VERSION ) - else: - url = "http://%s/%s%s" % (server,PartialPath,getstr) - - if dopostdata: - curl.setopt(pycurl.POSTFIELDS, postdata) - - curl.setopt(pycurl.URL, url) - self.Message( "URL: %s" % url ) - - # setup the output buffer - buffer = StringIO() - curl.setopt(pycurl.WRITEFUNCTION, buffer.write) - - try: - self.Message( "Fetching..." ) - curl.perform() - self.Message( "Done." ) - - http_result= curl.getinfo(pycurl.HTTP_CODE) - curl.close() - - # check the code, return the string only if it was successfull - if http_result == self.HTTP_SUCCESS: - self.Message( "Successfull!" ) - return buffer.getvalue() - else: - self.Message( "Failure, resultant http code: %d" % \ - http_result ) - return None - - except pycurl.error, err: - errno, errstr= err - self.Error( "connect to %s failed; curl error %d: '%s'\n" % - (server,errno,errstr) ) - - self.Error( "Unable to successfully contact any boot servers.\n" ) - return None - - + return ret def DownloadFile(self, PartialPath, GetVars, PostVars, DoSSL, DoCertCheck, DestFilePath, - ConnectTimeout= DEFAULT_CURL_CONNECT_TIMEOUT, - MaxTransferTime= DEFAULT_CURL_MAX_TRANSFER_TIME): + ConnectTimeout = DEFAULT_CURL_CONNECT_TIMEOUT, + MaxTransferTime = DEFAULT_CURL_MAX_TRANSFER_TIME, + FormData = None): - self.Message( "Attempting to retrieve %s" % PartialPath ) + self.Message("Attempting to retrieve {}".format(PartialPath)) # we can't do ssl and check the cert if we don't have a bootcd if DoSSL and DoCertCheck and not self.HAS_BOOTCD: - self.Error( "No boot cd exists (needed to use -c and -s.\n" ) + 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." ) + 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" ) + self.Error("Connect timeout must be greater than zero.\n") return 0 self.CheckProxy() - dopostdata= 0 + dopostdata = 0 # setup the post and get vars for the request if PostVars: - dopostdata= 1 + dopostdata = 1 postdata = urllib.urlencode(PostVars) - self.Message( "Posting data:\n%s\n" % postdata ) + self.Message("Posting data:\n{}\n".format(postdata)) - getstr= "" + getstr = "" if GetVars: - getstr= "?" + urllib.urlencode(GetVars) - self.Message( "Get data:\n%s\n" % getstr ) + getstr = "?" + urllib.urlencode(GetVars) + self.Message("Get data:\n{}\n".format(getstr)) # now, attempt to make the request, starting at the first # server in the list + if FormData: + cert_list = self.MONITORSERVER_CERTS + else: + cert_list = self.BOOTSERVER_CERTS - for server in self.BOOTSERVER_CERTS: - self.Message( "Contacting server %s." % server ) + for server in cert_list: + self.Message("Contacting server {}.".format(server)) - certpath = self.BOOTSERVER_CERTS[server] + certpath = cert_list[server] # output what we are going to be doing - self.Message( "Connect timeout is %s seconds" % \ - ConnectTimeout ) - - self.Message( "Max transfer time is %s seconds" % \ - MaxTransferTime ) + self.Message("Connect timeout is {} seconds".format(ConnectTimeout)) + self.Message("Max transfer time is {} seconds".format(MaxTransferTime)) if DoSSL: - url = "https://%s/%s%s" % (server,PartialPath,getstr) + url = "https://{}/{}{}".format(server, PartialPath, getstr) if DoCertCheck and PYCURL_LOADED: - self.Message( "Using SSL version %d and verifying peer." % - self.CURL_SSL_VERSION ) + self.Message("Using SSL version {} and verifying peer." + .format(self.CURL_SSL_VERSION)) else: - self.Message( "Using SSL version %d." % - self.CURL_SSL_VERSION ) + self.Message("Using SSL version {}." + .format(self.CURL_SSL_VERSION)) else: - url = "http://%s/%s%s" % (server,PartialPath,getstr) + url = "http://{}/{}{}".format(server, PartialPath, getstr) - self.Message( "URL: %s" % url ) + 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() + curl = pycurl.Curl() # don't want curl sending any signals curl.setopt(pycurl.NOSIGNAL, 1) @@ -409,7 +274,7 @@ class BootServerRequest: curl.setopt(pycurl.FOLLOWLOCATION, 0) if self.USE_PROXY: - curl.setopt(pycurl.PROXY, self.PROXY ) + curl.setopt(pycurl.PROXY, self.PROXY) if DoSSL: curl.setopt(pycurl.SSLVERSION, self.CURL_SSL_VERSION) @@ -424,36 +289,42 @@ class BootServerRequest: 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 = "%s " \ - "--connect-timeout %d " \ - "--max-time %d " \ + cmdline = "{} " \ + "--connect-timeout {} " \ + "--max-time {} " \ "--header Pragma: " \ - "--output %s " \ - "--fail " % \ - (self.CURL_CMD, ConnectTimeout, - MaxTransferTime, DestFilePath) + "--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 %s " % self.PROXY + cmdline = cmdline + "--proxy {} ".format(self.PROXY) if DoSSL: - cmdline = cmdline + "--sslv%d " % self.CURL_SSL_VERSION - + cmdline = cmdline + "--sslv{} ".format(self.CURL_SSL_VERSION) if DoCertCheck: - cmdline = cmdline + "--cacert %s " % certpath + cmdline = cmdline + "--cacert {} ".format(certpath) cmdline = cmdline + url - self.Message( "curl command: %s" % cmdline ) + self.Message("curl command: {}".format(cmdline)) if PYCURL_LOADED: @@ -461,57 +332,57 @@ class BootServerRequest: # setup the output file outfile = open(DestFilePath,"wb") - self.Message( "Opened output file %s" % DestFilePath ) + self.Message("Opened output file {}".format(DestFilePath)) curl.setopt(pycurl.WRITEDATA, outfile) - self.Message( "Fetching..." ) + self.Message("Fetching...") curl.perform() - self.Message( "Done." ) + self.Message("Done.") - http_result= curl.getinfo(pycurl.HTTP_CODE) + http_result = curl.getinfo(pycurl.HTTP_CODE) curl.close() outfile.close() - self.Message( "Results saved in %s" % DestFilePath ) + self.Message("Results saved in {}".format(DestFilePath)) # check the code, return 1 if successfull if http_result == self.HTTP_SUCCESS: - self.Message( "Successfull!" ) + self.Message("Successfull!") return 1 else: - self.Message( "Failure, resultant http code: %d" % \ - http_result ) + self.Message("Failure, resultant http code: {}" + .format(http_result)) - except pycurl.error, err: - errno, errstr= err - self.Error( "connect to %s failed; curl error %d: '%s'\n" % - (server,errno,errstr) ) + 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 + outfile.close() except OSError: pass else: - self.Message( "Fetching..." ) + self.Message("Fetching...") rc = os.system(cmdline) - self.Message( "Done." ) + self.Message("Done.") if rc != 0: try: - os.unlink( DestFilePath ) + os.unlink(DestFilePath) except OSError: pass - self.Message( "Failure, resultant curl code: %d" % rc ) - self.Message( "Removed %s" % DestFilePath ) + self.Message("Failure, resultant curl code: {}".format(rc)) + self.Message("Removed {}".format(DestFilePath)) else: - self.Message( "Successfull!" ) + self.Message("Successfull!") return 1 - self.Error( "Unable to successfully contact any boot servers.\n" ) + self.Error("Unable to successfully contact any boot servers.\n") return 0 @@ -541,10 +412,10 @@ if __name__ == "__main__": [ "output=", "verbose", \ "help","ssl","checkcert"]) - ssl= 0 - checkcert= 0 - output_file= None - verbose= 0 + ssl = 0 + checkcert = 0 + output_file = None + verbose = 0 for opt, arg in opt_list: if opt in ("-h","--help"): @@ -552,21 +423,21 @@ if __name__ == "__main__": sys.exit() if opt in ("-c","--checkcert"): - checkcert= 1 + checkcert = 1 if opt in ("-s","--ssl"): - ssl= 1 + ssl = 1 if opt in ("-o","--output"): - output_file= arg + output_file = arg if opt == "-v": - verbose= 1 + verbose = 1 if len(arg_list) != 1: raise Exception - partialpath= arg_list[0] + partialpath = arg_list[0] if string.lower(partialpath[:4]) == "http": raise Exception @@ -575,14 +446,14 @@ if __name__ == "__main__": sys.exit(2) # got the command line args straightened out - requestor= BootServerRequest(verbose) + requestor = BootServerRequest(verbose) if output_file: - requestor.DownloadFile( partialpath, None, None, ssl, + requestor.DownloadFile(partialpath, None, None, ssl, checkcert, output_file) else: - result= requestor.MakeRequest( partialpath, None, None, ssl, checkcert) + result = requestor.MakeRequest(partialpath, None, None, ssl, checkcert) if result: - print result + print(result) else: sys.exit(1)