source: MGET/Trunk/PythonPackage/src/GeoEco/ReportInstallation.py @ 1458

Revision 1260, 17.6 KB checked in by jjr8, 3 years ago (diff)

Merged revision(s) 1237-1259 from MGET/Branches/Jason:

  • Incremented build number.
  • Fixed bug in eddy detection code (NameError?: global name 'Dataset' is not defined).

........
Rebuilt ArcGIS 9.3 toolbox.

........

  • Added optional automaticallyDelete parameter to TemporaryDirectory? constructor, for testing purposes.
  • Enhanced NetCDF conversion tool to automatically treat NaN and Inf as "no data".
  • Updated HYCOM GOM tool to work with expt_32.5
  • Added support for MERIS data to the NASA OceanColor? L3 tools. Fixed support for CZCS which was broken by a NASA update to the data.
  • Fixed classification of Oceanic Nino Index (ONI) values into episode types, to exactly match what is done by http://www.cpc.ncep.noaa.gov/products/analysis_monitoring/ensostuff/ensoyears.shtml
  • Improved customizations to httplib2 to allow Unicode text to appear in exception text.
  • Added additional date/time formats to MGET's parser, to support ArcGIS date/time parameters in additional locales.

........
Added support for HYCOM GLBu0.08.
........
Rebuilt ArcGIS 9.3 toolbox.

........

  • Added CannyEdgeDetection? class and related tools.
  • Fixed bugs in new HYCOM GLBu0.08 tools found in testing.

........
Rebuilt ArcGIS 9.3 toolbox.

........
Created Canny edge detection tools for HYCOM datasets.
........
Rebuilt ArcGIS 9.3 toolbox.

........
Fixed bug in the toolbox and rebuilt it.

........
Fixed some bugs in the HYCOM tools found in testing.
........
Added Canny edge detection tools for MODIS L3 SST, GHRSST L4, and Pathfinder 5.0/5.1 SST.
........
Rebuilt ArcGIS 9.3 toolbox.

........
Fixed a bug found in testing.
........
Rebuilt ArcGIS 9.3 toolbox.

........
Rebuilt the installation packages. This will be merged with the Trunk and released as MGET 0.8a57.
........

  • For some reason, the Aviso Mediterranean Sea datasets have (cell-center) longitudes ranging from 354.0625-396.9375. ArcGIS cannot handle rasters that have a geographic longitudinal extent of 354-397. Adjusted Aviso code to shift these by -360.
  • Fixed bugs in the connectivity tools that prevented them from using the new Aviso DUACS 2014 data properly.

........

  • Added support for numpy 1.8.2, 1.9.0, 1.9.1, and 1.9.2
  • Added support for R 3.1.2 and 3.1.3

........
Added support for installing MGET on ArcGIS 10.3.
........
Added support for the nb and tw distributions to Fit GAM.
........
Rebuilt ArcGIS 9.3 toolbox.

........
Fixed bug relating to adding support for the nb and tw distributions to Fit GAM.
........
Rebuilt the installation packages. This will be merged with the Trunk and released as MGET 0.8a57.
........

Line 
1# ReportInstallation.py - reports an MGET installation to the MGET statistics server
2#
3# This program is only intended to be invoked by the GeoEco setup
4# program. The setup program uses it to report a successful or failed
5# installation to the server that tracks installation statistics.
6# Please do not invoke this program yourself. Doing so will corrupt
7# the statistics. We use these statistics to assess the software
8# quality of the setup program, identify common installation problems
9# encountered by MGET users, and justify our requests for additional
10# funding.
11#
12# For more information about this program, including a discussion of
13# what data are reported, what we do with the data, and how to disable
14# the reporting, please see the MGET web site. Alternatively, just
15# look at the code below. If you have any questions, please contact
16# Jason Roberts (jason.roberts@duke.edu).
17#
18# Copyright (C) 2009 Jason J. Roberts
19#
20# This program is free software; you can redistribute it and/or
21# modify it under the terms of the GNU General Public License
22# as published by the Free Software Foundation; either version 2
23# of the License, or (at your option) any later version.
24#
25# This program is distributed in the hope that it will be useful,
26# but WITHOUT ANY WARRANTY; without even the implied warranty of
27# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28# GNU General Public License (available in the file LICENSE.TXT)
29# for more details.
30#
31# You should have received a copy of the GNU General Public License
32# along with this program; if not, write to the Free Software
33# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
34
35import ConfigParser
36import os
37import re
38import socket
39import sys
40import tempfile
41import time
42import traceback
43import urllib
44import xmlrpclib
45
46import pywintypes
47import win32api
48import win32con
49
50def main():
51
52    # Validate that we have been invoked from the command line.
53
54    if sys.argv[0] != __file__:
55        raise RuntimeError('This function is only intended to be invoked by the GeoEco setup program. The setup program uses it to report a successful or failed installation to the server that tracks installation statistics. Please do not invoke this function yourself. Doing so will corrupt our statistics. Thank you.')
56
57    # Open a log file in the user's temp directory.
58
59    logFileHandle, logFilePath = tempfile.mkstemp('.txt', 'GeoEcoSetupFailure_')
60    logFile = os.fdopen(logFileHandle, 'wb')
61    try:
62        try:
63            logFile.write('Installation completed at %s GMT.\n' % time.asctime(time.gmtime(time.time())))
64           
65            # Parse and validate the command line arguments.
66
67            logFile.write('Parsing command line arguments.\n')
68           
69            try:
70                if len(sys.argv) != 4:
71                    raise RuntimeError('Invalid number of arguments.')
72
73                if sys.argv[1] not in ['False', 'True']:
74                    raise RuntimeError('Invalid arguments.')
75                shortcuts = sys.argv[1] == 'True'
76                logFile.write('shortcuts = %s\n' % str(shortcuts))
77
78                if sys.argv[2] not in ['False', 'True']:
79                    raise RuntimeError('Invalid arguments.')
80                arcToolbox = sys.argv[2] == 'True'
81                logFile.write('arcToolbox = %s\n' % str(arcToolbox))
82
83                if sys.argv[3] not in ['False', 'True']:
84                    raise RuntimeError('Invalid arguments.')
85                comClasses = sys.argv[3] == 'True'
86                logFile.write('comClasses = %s\n' % str(comClasses))
87               
88            except Exception, e:
89                sys.stderr.write('%s: %s\n' % (str(e.__class__.__name__), str(e)))
90                print('')
91                print('ReportInstallation.py - reports an MGET installation to the MGET statistics server')
92                print('')
93                print('This program is only intended to be invoked by the GeoEco setup program. The')
94                print('setup program uses it to report a successful or failed installation to the')
95                print('server that tracks installation statistics. Please do not invoke this program')
96                print('yourself. Doing so will corrupt the statistics. We use these statistics to')
97                print('assess the software quality of the setup program, identify common installation')
98                print('problems encountered by MGET users, and justify our requests for additional')
99                print('funding.')
100                print('')
101                print('For more information about this program, including a discussion of what data are')
102                print('reported, what we do with the data, and how to disable the reporting, please see')
103                print('the MGET web site. You are also welcome to examine the program source code. If')
104                print('you have any questions, please contact Jason Roberts (jason.roberts@duke.edu).')
105                print('')
106                print('Thanks for your support,')
107                print('')
108                print('    - The MGET Development Team')
109                sys.exit(1)
110
111            # Look up the ID of this client MGET's registry key. If no client
112            # ID is there, generate one randomly. The client ID is a random
113            # 128-bit number (a GUID) that is guaranteed by the operating
114            # system to be unique globally.
115
116            logFile.write('Creating/opening registry key HLKM\\SOFTWARE\\GeoEco.\n')
117            hKey = win32api.RegCreateKey(win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\GeoEco')
118            try:
119                # First see if there is a value called
120                # DisableInstallationReporting. If so, it means the user
121                # requested that no installation report be sent to the server
122                # and we must exit immediately.
123
124                try:
125                    logFile.write('Querying for the DisableInstallationReporting value.\n')
126                    win32api.RegQueryValueEx(hKey, 'DisableInstallationReporting')
127                except:
128                    logFile.write('The DisableInstallationReporting value could not be queried. Installation reporting is not disabled.\n')
129                else:
130                    logFile.write('The DisableInstallationReporting was successfully queried. Installation reporting is disabled. Exiting without sending a report.\n')
131                    print('Installation reporting has been disabled. Exiting without sending a report.')
132                    return
133
134                # Now try to read the ClientID value.
135
136                clientID = None
137               
138                try:
139                    logFile.write('Querying for the ClientID value.\n')
140                    clientID = win32api.RegQueryValueEx(hKey, 'ClientID')[0]
141                except:
142                    logFile.write('Failed to query the ClientID value.\n')
143
144                # If we failed to read a ClientID value or we got one that is
145                # an invalid format, generate a new one.
146
147                if not isinstance(clientID, basestring) or re.match('\{[0123456789AaBbCcDdEeFf]{8}-[0123456789AaBbCcDdEeFf]{4}-[0123456789AaBbCcDdEeFf]{4}-[0123456789AaBbCcDdEeFf]{4}-[0123456789AaBbCcDdEeFf]{12}\}', clientID) is None:
148                    clientID = str(pywintypes.CreateGuid())
149                    logFile.write('Writing ClientID value "%s".\n' % clientID)
150                    win32api.RegSetValueEx(hKey, 'ClientID', 0, win32con.REG_SZ, clientID)
151                else:
152                    clientID = clientID.upper()
153                    logFile.write('clientID = %s.\n' % clientID)
154               
155            finally:
156                logFile.write('Closing the registry key.\n')
157                win32api.RegCloseKey(hKey)
158
159            # Get the MGET version number. This should always succeed, because
160            # we are only invoked from the MGET post-installation script,
161            # which distutils should only invoke if it was able to copy the
162            # Python files onto the machine and compile them.
163
164            mgetVer = None
165            try:
166                logFile.write('Importing GeoEco.\n')
167                import GeoEco
168                mgetVer = GeoEco.__version__
169            except Exception, e:
170                logFile.write('Failed to import GeoEco: %s: %s\n' % (str(e.__class__.__name__), str(e)))
171            else:
172                logFile.write('mgetVer = %s\n' % mgetVer)
173
174            # Get the ArcGIS version number from the registry. This will fail
175            # if ArcGIS is not installed, in which case we send None to the
176            # server.
177
178            arcVer = None
179            try:
180                logFile.write('Opening registry key HLKM\\SOFTWARE\\ESRI\\Desktop10.3.\n')
181                try:
182                    hkey = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\ESRI\\Desktop10.3')
183                except:
184                    try:
185                        logFile.write('Failed to open the registry key.\n')
186                        logFile.write('Opening registry key HLKM\\SOFTWARE\\ESRI\\Desktop10.2.\n')
187                        hkey = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\ESRI\\Desktop10.2')
188                    except:
189                        try:
190                            logFile.write('Failed to open the registry key.\n')
191                            logFile.write('Opening registry key HLKM\\SOFTWARE\\ESRI\\Desktop10.1.\n')
192                            hkey = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\ESRI\\Desktop10.1')
193                        except:
194                            try:
195                                logFile.write('Failed to open the registry key.\n')
196                                logFile.write('Opening registry key HLKM\\SOFTWARE\\ESRI\\Desktop10.0.\n')
197                                hkey = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\ESRI\\Desktop10.0')
198                            except:
199                                logFile.write('Failed to open the registry key.\n')
200                                logFile.write('Opening registry key HLKM\\SOFTWARE\\ESRI\\ArcInfo\\Desktop\\8.0.\n')
201                                hkey = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\ESRI\\ArcInfo\\Desktop\\8.0')
202                try:
203                    logFile.write('Querying for the RealVersion value.\n')
204                    realVersion = win32api.RegQueryValueEx(hkey, 'RealVersion')[0].strip()
205                    try:
206                        logFile.write('Querying for the SPNumber value.\n')
207                        spNumber = win32api.RegQueryValueEx(hkey, 'SPNumber')[0].strip()
208                    except:
209                        spNumber = None
210                finally:
211                    logFile.write('Closing the registry key.\n')
212                    win32api.RegCloseKey(hkey)
213
214                if spNumber is None or spNumber == '0':
215                    arcVer = realVersion
216                elif realVersion == '9.3' and spNumber == '2':
217                    arcVer = '9.3.1'
218                elif realVersion == '9.3' and spNumber > '2':
219                    arcVer = '9.3.1 SP%i' % (int(spNumber) - 2)
220                else:
221                    arcVer = '%s SP%s' % (realVersion, spNumber)
222
223            except Exception, e:
224                logFile.write('Failed to get ArcGIS version number: %s: %s\n' % (str(e.__class__.__name__), str(e)))
225            else:
226                logFile.write('arcVer = %s\n' % arcVer)
227
228            # Get the R version using logic that imitates what rpy's
229            # get_R_VERSION function does. (I originally tried to use that
230            # function but it would not work if the registry key did not exist
231            # and it tried to run R.exe instead.)
232
233            rVer = None
234            try:
235                # First try to read the "Current Version" value of the
236                # HKLM\SOFTWARE\R-core\R registry key.
237               
238                try:
239                    logFile.write('Opening registry key HLKM\\SOFTWARE\\R-core\\R.\n')
240                    hkey = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\R-core\\R')
241                    try:
242                        logFile.write('Querying for the Current Version value.\n')
243                        rVer = win32api.RegQueryValueEx(hkey, 'Current Version')[0]
244                    finally:
245                        logFile.write('Closing the registry key.\n')
246                        win32api.RegCloseKey(hkey)
247
248                # If that did not work, try to parse the R version from the
249                # R_HOME environment variable.
250               
251                except:
252                    logFile.write('Failed. Trying the R_HOME environment variable instead.\n')
253                    if os.environ.has_key('R_HOME'):
254                        rHome = os.environ['R_HOME']
255                        if re.match('^[Rr]-\d+\.\d+\.\d+$', os.path.basename(rHome)):
256                            rVer = os.path.basename(rHome)[2:]
257
258                        # If that did not work, look for a file called
259                        # README.R-X.Y.Z in the R_HOME directory, where X.Y.Z
260                        # is the version number.
261                       
262                        else:
263                            import glob
264                            files = glob.glob(os.path.join(rHome, 'README.R-[0123456789].*.*'))
265                            if len(files) > 0 and re.match('^\d+\.\d+\.\d+$', os.path.basename(files[0])[9:]) is not None:
266                                rVer = os.path.basename(files[0])[9:]
267
268            except Exception, e:
269                logFile.write('Failed to get R version number: %s: %s\n' % (str(e.__class__.__name__), str(e)))
270            else:
271                logFile.write('rVer = %s\n' % rVer)
272
273            # Download the ClientConfiguration.ini file from the well-known
274            # location and look up the URL to the XML-RPC web service that
275            # will accept the installation report.
276            #
277            # In order to prevent this script from hanging if the Duke
278            # servers are not working, we set the default socket timeout
279            # to 60 seconds. (With Python, there is no way to set it on a
280            # per-connection basis, at least using urllib and xmlrpclib.)
281            # But Python 2.4 contains a bug that causes this to break SSL
282            # support (see http://bugs.python.org/issue1153016). So, on
283            # 2.4, convert https URLs to http URLs.
284
285            logFile.write('Setting the socket default timeout to 60.\n')
286
287            socket.setdefaulttimeout(60)
288
289            if sys.version_info[0] == 2 and sys.version_info[1] == 4:
290                clientINIURL = 'http://code.nicholas.duke.edu/projects/mget/browser/Statistics/ClientConfiguration.ini?format=txt'
291            else:
292                clientINIURL = 'https://code.nicholas.duke.edu/projects/mget/browser/Statistics/ClientConfiguration.ini?format=txt'
293
294            logFile.write('clientINIURL = %s\n' % clientINIURL)
295
296            try:
297                iniFileError = 'Step 1: '
298                config = ConfigParser.ConfigParser()
299                logFile.write('Opening the clientINIURL.\n')
300                iniFileError = 'Step 2: '
301                f = urllib.urlopen(clientINIURL)
302                try:
303                    logFile.write('Parsing the INI file.\n')
304                    iniFileError = 'Step 3: '
305                    config.readfp(f)
306                finally:
307                    iniFileError = 'Step 4: '
308                    f.close()
309                logFile.write('Getting the URL from the parsed INI file.\n')
310                iniFileError = 'Step 5: '
311                serverURL = config.get('V1', 'URL')
312            except Exception, e:
313                logFile.write('Failed to get the MGET server URL: %s: %s. The default URL will be used.\n' % (str(e.__class__.__name__), str(e)))
314                serverURL = 'http://mgetstats.nicholas.duke.edu:8001'
315                iniFileError = '%s%s: %s' % (iniFileError, str(e.__class__.__name__), str(e))
316            else:
317                iniFileError = None
318
319            logFile.write('serverURL = %s\n' % serverURL)
320
321            if sys.version_info[0] == 2 and sys.version_info[1] == 4 and serverURL.startswith('https:'):
322                logFile.write('Changing serverURL to http from https because we\'re running on Python 2.4.\n')
323                serverURL = 'http:' + serverURL[6:]
324
325            # Send the report to the server by calling its XML-RPC web
326            # service.
327
328            logFile.write('Instantiating the xmlrpclib.Server object.\n')
329            s = xmlrpclib.Server(serverURL, allow_none=True)
330           
331            logFile.write('Calling ReportMGETInstallationV2 on the server.\n')
332            s.ReportMGETInstallationV2(clientID, shortcuts, arcToolbox, comClasses, mgetVer, '.'.join(map(str, sys.version_info[0:3])), arcVer, rVer, iniFileError)
333
334        # If we got any kind of exception, write it to the log file.
335
336        except:
337            try:
338                logFile.write('Caught an exception:\n')
339                logFile.write('\n')
340                logFile.write(traceback.format_exc())
341            except:
342                pass
343            raise
344
345    # Close the log file.
346
347    finally:
348        try:
349            logFile.close()
350        except:
351            pass
352
353    # If we got to here, we succesfully sent the report to the server.
354    # Delete the log file.
355
356    os.remove(logFilePath)
357
358if __name__ == '__main__':
359    main()
Note: See TracBrowser for help on using the repository browser.