#!/usr/bin/python
# ######################################################################
# ESX3 Patch Downloader
# Angelo Conforti <angeloxx@angeloxx.it>
# Download ESX patches directly from VMware repo
#
# 0.1 07.05.17 - First release
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# you should have received a copy of the GNU General Public License
# along with this program (or with Nagios);  if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA
#
# ######################################################################

import sys, StringIO
import pycurl, urllib, re, os
from optparse import OptionParser


class ESX_DOWNLOAD:
    url_index = "http://www.vmware.com/download/vi/vi3_patches.html#c4310"
    patch_uri = "http://download3.vmware.com/software/vi/"
    def download_index(self):
        b = StringIO.StringIO()
        c = pycurl.Curl()
        c.setopt(pycurl.URL, ESX_DOWNLOAD.url_index)
        c.setopt(pycurl.FOLLOWLOCATION, 1)
        c.setopt(pycurl.MAXREDIRS, 5)
        c.setopt(pycurl.NOSIGNAL, 1)
        c.setopt(pycurl.USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)")
        c.setopt(pycurl.WRITEFUNCTION, b.write)
        c.perform()
        c.close()
        contents = b.getvalue()
        patches = re.compile('<h3>(.*?)</h3>[\r|\n|\t]+<p><strong>Patches(.*)</p>')
        return patches.findall(contents)
        
    def get_index(self,version):
        esxindex = self.download_index()
        for element in esxindex:
                if (element[0] == version):
                    # Questa e' la versione di interesse, quali sono le patch?
                    # (le patch sono fornite in ordine discendente, quindi l'ordine di installazione e' contrario)
                    patches = re.compile('<a href=".*?" >(ESX-\d+) Patch</a> \| (\d+/\d+/\d+)')
                    return patches.findall(element[1])

    def save_index(self,file,esxindex):
        f = open(file, "wb")
        print "[JOB] saving patches index into '%s' file" % file
        for element in esxindex:
            f.write(element[0] +  "|" + element[1] + "\r")

    def get_versions(self,version):
        esxindex = self.download_index()
        for element in esxindex:
                print element[0]

    def download_patch(self,path,esxindex):
        for element in esxindex:
                if os.path.exists(path + element[0] + ".tgz"):
                    print "[JOB] Patch [%s] - already into repository -> skipping" % element[0]
                else:
                    print "[JOB] Patch [%s] - not into repository -> downloading" % element[0]
                    self.download_only(ESX_DOWNLOAD.patch_uri + element[0] + ".tgz",path + element[0] + ".tgz")
                    
    def download_only(self,uri,outfile):
        f = open(outfile, "wb")
        c = pycurl.Curl()
        c.setopt(pycurl.FOLLOWLOCATION, 1)
        c.setopt(pycurl.MAXREDIRS, 5)
        c.setopt(pycurl.NOSIGNAL, 0)
        c.setopt(pycurl.TIMEOUT, 300)
        c.setopt(pycurl.USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)")
        c.setopt(pycurl.URL, uri)
        c.setopt(pycurl.WRITEFUNCTION, f.write)
        c.perform()
        c.close()
        f.close()
        

print "VMware ESX3 patch download 0.1py"
print "(C) 1992-2007 Angelo Conforti (angeloxx@angeloxx.it)"
print "This program is provided as-is under GPL License"
print "--"

product = 'ESX Server 3.0.1'
outpath = 'C:\\'


parser = OptionParser()
parser.add_option("-o", "--outpath",        dest="outpath",     help="Download path", default=None)
parser.add_option("-d", "--download",       dest="download",    help="Download patches", default=False, action="store_true")
parser.add_option("-p", "--product",        dest="product",     help="Product [ESX Server 3.0.0 - ESX Server 3.0.1 - VMware VirtualCenter 2.0.1]", default=None)

(options, args) = parser.parse_args()
if not options.product:
    print ("[INFO] product not specified, using default [%s]" % product)
else:
    product = options.product
    print ("[INFO] product specified [%s]" % product)
    
if not options.outpath:
    print ("[INFO] outpath not specified, using default [%s]" % outpath)
else:
    outpath = options.outpath
    print ("[INFO] outpath specified [%s]" % outpath)
if options.download:
    download = 1
    print ("[INFO] patch download requested")

t = ESX_DOWNLOAD()
index = t.get_index("ESX Server 3.0.1");
if len(index) == 0:
    print "[ERR] no patch found for %s product (correct product name ?!?)" %  product
    sys.exit(1)
    
print "[INFO] found %03d patches for %s product" % (len(index),product)
index.reverse()
t.save_index(outpath + "patchindex.txt",index)
if download:
    t.download_patch(outpath,index)
    
print "[INFO] all done. Good luck!"