source: TI12-security/trunk/python/ndg-security-install.py @ 3047

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg-security-install.py@3047
Revision 3047, 12.8 KB checked in by pjkersha, 12 years ago (diff)

ndg.security.server/setup.py,
ndg.security.server/ndg/security/server/MyProxy.py,
setup.py,
ndg.security.client/setup.py,
ndg.security.test/setup.py,
ndg.security.common/setup.py: revised overall version to reflect important fixes to AA and getSessionStatus method add to SM

ndg-security-install.py: conf dir is now automatically copied to /etc/ndg/security default location. conf.x created where x is current egg version. A symlink to this from conf/ is created.

  • Property svn:executable set to *
Line 
1#!/usr/bin/env python
2"""Install NDG Server package with M2Crypto build settings and to include
3Twisted
4
5NERC Data Grid Project
6"""
7__author__ = "P J Kershaw"
8__date__ = "15/03/07"
9__copyright__ = "(C) 2007 STFC & NERC"
10__license__ = \
11"""This software may be distributed under the terms of the Q Public
12License, version 1.0 or later."""
13__contact__ = "P.J.Kershaw@rl.ac.uk"
14__revision__ = '$Id$'
15
16
17import os, sys
18import pkg_resources # Locate ndg.security.server.conf dir
19import shutil # For creating config dir
20import urllib
21import optparse
22from ConfigParser import SafeConfigParser
23from subprocess import call
24from setuptools.command.easy_install import main
25
26import logging
27log = logging.getLogger(__name__)
28     
29class SecurityInstallError(Exception):
30    """Errors related to security installation"""
31   
32class SecurityInstall(object):
33    '''Wrapper class for NDG security installation
34   
35    A wrapper is required over and above easy_install as additional setup
36    steps are required to enable for example custom build settings for
37    M2Crypto
38   
39    @cvar dependencyLink: default location for dependencies
40    @type dependencyLink: string
41   
42    @cvar defaultTwistedURI: default location for Twisted download
43    @type param: string
44   
45    @cvar configDir: default location for configuration directory "conf"
46    @type configDir: string'''
47   
48    dependencyLink = "http://ndg.nerc.ac.uk/dist/" 
49    defaultTwistedURI = \
50'http://tmrc.mit.edu/mirror/twisted/Twisted/2.2/TwistedSumo-2006-02-12.tar.bz2'
51    configDir = os.path.join("/etc", "ndg", "security", "conf")
52   
53    def __call__(self):
54        self.main()
55       
56    def main(self):
57        '''Parse command line args and execute the installation'''
58       
59        parser = optparse.OptionParser()
60       
61        parser.add_option("-a",
62                          "--install-all",
63                          dest="installAll",
64                          action="store_true",
65                          default=False,
66                          help="Install client AND server packages.")
67       
68        parser.add_option("-c",
69                          "--install-client",
70                          dest="installClient",
71                          action="store_true",
72                          default=False,
73                          help="Install client package only.")
74       
75        parser.add_option("-s",
76                          "--install-server",
77                          dest="installServer",
78                          action="store_true",
79                          default=False,
80                          help="Install server package only.")
81       
82        parser.add_option("-u",
83                          "--install-unittests",
84                          dest="installUnitTests",
85                          action="store_true",
86                          default=False,
87                          help="Install unit test package only.")
88       
89        parser.add_option("-o",
90                          "--openssl-path",
91                          dest="opensslPath",
92                          default='/usr/local/ssl',
93                          help="Path to openssl for M2Crypto to link with")
94       
95        parser.add_option("-n",
96                          "--no-twisted",
97                          dest="noTwisted",
98                          action="store_true",
99                          default=False,
100                          help=\
101"""Skip Twisted install.  This option applies to the \"all\" and \"server\"
102package options only.  Twisted is not needed for the client.""")
103       
104        parser.add_option("-t",
105                          "--twisted-uri",
106                          dest="twistedURI",
107                          default=self.__class__.defaultTwistedURI,
108                          help=\
109"""Provide an alternative location for Twisted download.  A .tar.bz type file
110is expected.  The default is \"%s\"""" % self.__class__.defaultTwistedURI)
111       
112        parser.add_option("-f",
113                          "--find-links",
114                          dest="dependencyLinks",
115                          default=self.__class__.dependencyLink,
116                          help=\
117                      'Set URLs to locate packages.  The default is "%s"' % \
118                      self.__class__.dependencyLink)
119       
120        parser.add_option("-U",
121                          "--upgrade",
122                          dest="upgrade",
123                          action="store_true",
124                          default=False,
125                          help=\
126          'force upgrade (search PyPI/dependency links for latest version)')
127   
128        configOpts = ("-C", "--config-dir")
129        parser.add_option(dest="configDir",
130                          default=self.__class__.configDir,
131                          help=\
132"""Specify a location for configuration files (server package only).  The
133default is \"%s\"""" % self.__class__.configDir,
134                          *configOpts)
135   
136        self.opt, args = parser.parse_args()
137   
138        # Sanity check
139        nInstallArgs = sum((self.opt.installClient, 
140                            self.opt.installServer,
141                            self.opt.installUnitTests, 
142                            self.opt.installAll))
143        if not nInstallArgs:
144            parser.error("At least one install option must be set")
145           
146        elif nInstallArgs > 1:
147            parser.error("Only one install option may be set")
148 
149        # Set M2Crypto build settings in a distutils config file
150        self.initM2CryptoDependencies() 
151   
152        # Installation based on flags set
153        if self.opt.upgrade:
154            args = ['-U']
155        else:
156            args = []
157     
158        # Add links for dependencies 
159        args += ['-f', self.opt.dependencyLinks]
160
161        if self.opt.installClient:
162            log.info("Installing ndg-security-client ...")
163            args += ["ndg_security_client"]
164            main(args)
165           
166        elif self.opt.installServer:
167            log.info("Installing ndg-security-server ...")
168            args += ["ndg_security_server"]
169            main(args)
170            self.installTwisted()
171           
172            # Config dir is part of server package only
173            self.createConfigDir()
174           
175        elif self.opt.installUnitTests:
176            log.info("Installing ndg-security-test ...")
177            args += ["ndg_security_test"]
178            main(args)
179            self.installTwisted()
180           
181        elif self.opt.installAll:
182            log.info("Installing all ...")
183            ndgSecurityArgs = args + ["ndg_security"]
184            main(ndgSecurityArgs)
185            ndgSecurityTestArgs = args + ["ndg_security_test"]
186            main(ndgSecurityArgs)
187            self.installTwisted()
188           
189            # Config dir is part of server package
190            self.createConfigDir()
191           
192           
193    def initM2CryptoDependencies(self):       
194        '''Set-up link path for openssl for M2Crypto build by creating a
195        distutils config file containing the include file and library file
196        paths'''
197        log.info("Initialising M2Crypto set-up ...")
198       
199        opensslInclPath = os.path.join(self.opt.opensslPath, 'include')
200        opensslLibPath = os.path.join(self.opt.opensslPath, 'lib')
201       
202        distutilsCfgFilePath = os.path.join(sys.prefix,
203                                            'lib',
204                                            'python%s' % sys.version[:3],
205                                            'distutils',
206                                            'distutils.cfg')
207        configParser = SafeConfigParser()
208       
209        if configParser.read(distutilsCfgFilePath):
210            # File already exists
211            if not configParser.has_section('build_ext'):
212                configParser.add_section('build_ext')
213           
214            if configParser.has_option('build_ext', 'include_dirs'):
215                existingInclDirs=configParser.get('build_ext', 'include_dirs')
216               
217                if opensslInclPath not in existingInclDirs.split():
218                    includeDirs = "%s %s" % (opensslInclPath,existingInclDirs)
219                    configParser.set('build_ext', 'include_dirs', includeDirs)
220            else:
221                configParser.set('build_ext', 'include_dirs', opensslInclPath)
222           
223            if configParser.has_option('build_ext', 'library_dirs'):
224                existingLibDirs = configParser.get('build_ext','library_dirs')
225               
226                if opensslLibPath not in existingLibDirs.split():
227                    libraryDirs = "%s %s" % (opensslLibPath, existingLibDirs)
228                    configParser.set('build_ext', 'library_dirs', libraryDirs)
229            else:
230                configParser.set('build_ext', 'library_dirs', opensslLibPath)
231                                 
232        else:
233            # No config file present - make one
234            configParser.add_section('build_ext')
235            configParser.set('build_ext', 'include_dirs', opensslInclPath)
236            configParser.set('build_ext', 'library_dirs', opensslLibPath)
237           
238        configParser.write(open(distutilsCfgFilePath, 'w'))
239   
240   
241    def installTwisted(self):
242        '''Download and install twisted manually as it is not egg compatible
243        '''
244       
245        if self.opt.noTwisted:
246            return
247       
248        log.info("Installing Twisted: %s ..." % self.opt.twistedURI)
249       
250        # Install Twisted sumo
251        try:
252            twistedTarBz = os.path.basename(self.opt.twistedURI)   
253            urllib.urlretrieve(self.opt.twistedURI, twistedTarBz)
254           
255        except IOError, (errMsg, e):
256            raise SecurityInstallError, \
257                'Error retrieving Twisted from "%s": %s' % \
258                                                (self.opt.twistedTarURI, e[1])
259        except Exception, e:
260            raise SecurityInstallError, \
261                'Error retrieving Twisted from "%s": %s' % \
262                                                (self.opt.twistedTarURI, e)
263
264        import tarfile
265       
266        twistedTar = tarfile.open(twistedTarBz, 'r:bz2')
267        for tarInfo in twistedTar:
268            twistedTar.extract(tarInfo)
269       
270        try:
271            twistedDir=os.path.splitext(os.path.splitext(twistedTarBz)[0])[0]
272        except Exception:
273            raise SecurityInstallError, \
274            'Error getting Twisted dir path from tar.bz file name: "%s"' % \
275                twistedTarBz
276       
277        os.chdir(twistedDir)
278        try: 
279            retCode = call([os.path.join(sys.prefix, 'bin', 'python'), 
280                            'setup.py', 
281                            'install'])
282        except OSError, e:
283            raise SecurityInstallError, \
284                        "Error calling setup install for Twisted: " + str(e)
285       
286        if retCode != 0:
287            raise SecurityInstallError, "Twisted setup install returned %d" %\
288                                        retCode
289       
290        os.chdir('..')
291
292
293    def createConfigDir(self):
294        """Copy configuration files for services from the server egg into
295        a config area.  The default is /etc/ndg/security/conf"""
296       
297        # Skip if not set
298        if not self.opt.configDir: 
299            return
300       
301        log.info('Copying configuration directory to "%s"'%self.opt.configDir)
302       
303        # Otherwise create - fix to rwx for owner and group only
304        confDirPath = os.path.dirname(self.opt.configDir)
305        try:
306            os.makedirs(confDirPath, mode=0770)
307        except OSError, e:
308            if e.errno != 17:
309                # errno=17 -> file already exists - it's OK if directory is
310                # already present
311                raise SecurityInstallError, \
312                   "Creating configuration directory: %s" % e
313       
314        # Locate conf directory in active egg
315        eggConfigDir = pkg_resources.resource_filename('ndg.security.server',
316                                                       'conf')
317        # Get distribution version info
318        serverDistro = pkg_resources.get_distribution('ndg-security-server')
319       
320        configDirVers = "%s.%s" % (self.opt.configDir, serverDistro.version)
321        # Copy over conf directory from egg
322        try:
323            shutil.copytree(eggConfigDir, configDirVers)
324        except OSError, e:
325            if e.errno != 17:
326                raise SecurityInstallError, \
327                    "Copying configuration directory: %s" % e
328
329        try:
330            os.symlink(configDirVers, self.opt.configDir)
331        except OSError, e:
332            raise SecurityInstallError, \
333                "Making a symbolic link %s -> %s: %s" % (self.opt.configDir, 
334                                                         configDirVers, 
335                                                         e)
336if __name__ == "__main__":
337    SecurityInstall()()
338     
Note: See TracBrowser for help on using the repository browser.