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:
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
# 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
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
# 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)
# 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())
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)
os.unlink(buffer_name)
except OSError:
pass
-
+
return ret
def DownloadFile(self, PartialPath, GetVars, PostVars,
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")
dopostdata = 1
postdata = urllib.urlencode(PostVars)
self.Message("Posting data:\n{}\n".format(postdata))
-
+
getstr = ""
if GetVars:
getstr = "?" + urllib.urlencode(GetVars)
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:
.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(
"""
-o/--output <file> 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:],
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
if opt == "-v":
verbose = 1
-
+
if len(arg_list) != 1:
raise Exception
# 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: