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

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

Removed refs to Twisted in ndg-security-install. Twisted is no longer needed and even it needs to be re-instated it now supports egg based install.

  • Property svn:executable set to *
Line 
1#!/usr/bin/env python
2"""Install NDG Server package with M2Crypto build settings
3
4NERC Data Grid Project
5"""
6__author__ = "P J Kershaw"
7__date__ = "15/03/07"
8__copyright__ = "(C) 2007 STFC & NERC"
9__license__ = \
10"""This software may be distributed under the terms of the Q Public
11License, version 1.0 or later."""
12__contact__ = "Philip.Kershaw@stfc.ac.uk"
13__revision__ = '$Id$'
14
15
16import os, sys
17import shutil # For creating config dir
18import urllib
19import optparse
20from ConfigParser import SafeConfigParser
21from subprocess import call
22from setuptools.command.easy_install import main
23
24import logging
25log = logging.getLogger(__name__)
26     
27class SecurityInstallError(Exception):
28    """Errors related to security installation"""
29   
30class SecurityInstall(object):
31    '''Wrapper class for NDG security installation
32   
33    A wrapper is required over and above easy_install as additional setup
34    steps are required to enable for example custom build settings for
35    M2Crypto
36   
37    @cvar dependencyLink: default location for dependencies
38    @type dependencyLink: string
39   
40    @cvar configDir: default location for configuration directory "conf"
41    @type configDir: string'''
42   
43    dependencyLink = "http://ndg.nerc.ac.uk/dist/" 
44    configDir = os.path.join("/etc", "ndg", "security", "conf")
45   
46    def __call__(self):
47        self.main()
48       
49    def main(self):
50        '''Parse command line args and execute the installation'''
51       
52        parser = optparse.OptionParser()
53       
54        parser.add_option("-a",
55                          "--install-all",
56                          dest="installAll",
57                          action="store_true",
58                          default=False,
59                          help="Install client AND server packages.")
60       
61        parser.add_option("-c",
62                          "--install-client",
63                          dest="installClient",
64                          action="store_true",
65                          default=False,
66                          help="Install client package only.")
67       
68        parser.add_option("-s",
69                          "--install-server",
70                          dest="installServer",
71                          action="store_true",
72                          default=False,
73                          help="Install server package only.")
74       
75        parser.add_option("-u",
76                          "--install-unittests",
77                          dest="installUnitTests",
78                          action="store_true",
79                          default=False,
80                          help="Install unit test package only.")
81       
82        parser.add_option("-o",
83                          "--openssl-path",
84                          dest="opensslPath",
85                          default='/usr/local/ssl',
86                          help="Path to openssl for M2Crypto to link with")
87       
88        parser.add_option("-f",
89                          "--find-links",
90                          dest="dependencyLinks",
91                          default=self.__class__.dependencyLink,
92                          help=\
93                      'Set URLs to locate packages.  The default is "%s"' % \
94                      self.__class__.dependencyLink)
95       
96        parser.add_option("-U",
97                          "--upgrade",
98                          dest="upgrade",
99                          action="store_true",
100                          default=False,
101                          help=\
102          'force upgrade (search PyPI/dependency links for latest version)')
103   
104        configOpts = ("-C", "--config-dir")
105        parser.add_option(dest="configDir",
106                          default=self.__class__.configDir,
107                          help=\
108"""Specify a location for configuration files (server package only).  The
109default is \"%s\"""" % self.__class__.configDir,
110                          *configOpts)
111   
112        self.opt, args = parser.parse_args()
113   
114        # Sanity check
115        nInstallArgs = sum((self.opt.installClient, 
116                            self.opt.installServer,
117                            self.opt.installUnitTests, 
118                            self.opt.installAll))
119        if not nInstallArgs:
120            parser.error("At least one install option must be set")
121           
122        elif nInstallArgs > 1:
123            parser.error("Only one install option may be set")
124 
125        # Set M2Crypto build settings in a distutils config file
126        self.initM2CryptoDependencies() 
127   
128        # Installation based on flags set
129        if self.opt.upgrade:
130            args = ['-U']
131        else:
132            args = []
133     
134        # Add links for dependencies 
135        args += ['-f', self.opt.dependencyLinks]
136
137        if self.opt.installClient:
138            log.info("Installing ndg-security-client ...")
139            args += ["ndg_security_client"]
140            main(args)
141           
142        elif self.opt.installServer:
143            log.info("Installing ndg-security-server ...")
144            args += ["ndg_security_server"]
145            main(args)
146           
147            # Config dir is part of server package only
148            self.createConfigDir()
149           
150        elif self.opt.installUnitTests:
151            log.info("Installing ndg-security-test ...")
152            args += ["ndg_security_test"]
153            main(args)
154           
155        elif self.opt.installAll:
156            log.info("Installing all ...")
157            args += ["ndg_security", "ndg_security_test"]
158            if self.opt.upgrade:
159                # If upgrade is set dependencies for ndg_security aren't
160                # updated - they need to be added explicitly
161                args += ["ndg_security_common", 
162                         "ndg_security_server",
163                         "ndg_security_client"] 
164            main(args)
165           
166            # Config dir is part of server package
167            self.createConfigDir()
168           
169           
170    def initM2CryptoDependencies(self):       
171        '''Set-up link path for openssl for M2Crypto build by creating a
172        distutils config file containing the include file and library file
173        paths'''
174        log.info("Initialising M2Crypto set-up ...")
175       
176        opensslInclPath = os.path.join(self.opt.opensslPath, 'include')
177        opensslLibPath = os.path.join(self.opt.opensslPath, 'lib')
178       
179        distutilsCfgFilePath = os.path.join(sys.prefix,
180                                            'lib',
181                                            'python%s' % sys.version[:3],
182                                            'distutils',
183                                            'distutils.cfg')
184        configParser = SafeConfigParser()
185       
186        if configParser.read(distutilsCfgFilePath):
187            # File already exists
188            if not configParser.has_section('build_ext'):
189                configParser.add_section('build_ext')
190           
191            if configParser.has_option('build_ext', 'include_dirs'):
192                existingInclDirs=configParser.get('build_ext', 'include_dirs')
193               
194                if opensslInclPath not in existingInclDirs.split():
195                    includeDirs = "%s %s" % (opensslInclPath,existingInclDirs)
196                    configParser.set('build_ext', 'include_dirs', includeDirs)
197            else:
198                configParser.set('build_ext', 'include_dirs', opensslInclPath)
199           
200            if configParser.has_option('build_ext', 'library_dirs'):
201                existingLibDirs = configParser.get('build_ext','library_dirs')
202               
203                if opensslLibPath not in existingLibDirs.split():
204                    libraryDirs = "%s %s" % (opensslLibPath, existingLibDirs)
205                    configParser.set('build_ext', 'library_dirs', libraryDirs)
206            else:
207                configParser.set('build_ext', 'library_dirs', opensslLibPath)
208                                 
209        else:
210            # No config file present - make one
211            configParser.add_section('build_ext')
212            configParser.set('build_ext', 'include_dirs', opensslInclPath)
213            configParser.set('build_ext', 'library_dirs', opensslLibPath)
214           
215        try:
216            configParser.write(open(distutilsCfgFilePath, 'w'))
217        except IOError:
218            # distutils dir may not be installed - try local dir as back-up
219            # option
220            distutilsCfgFilePath = os.path.join(os.environ['HOME'],
221                                                '.pydistutils.cfg')
222            configParser.write(open(distutilsCfgFilePath, 'w'))
223
224
225    def createConfigDir(self):
226        """Copy configuration files for services from the server egg into
227        a config area.  The default is /etc/ndg/security/conf"""
228       
229        # Skip if not set
230        if not self.opt.configDir: 
231            return
232       
233        log.info('Copying configuration directory to "%s"'%self.opt.configDir)
234       
235        # Otherwise create - fix to rwx for owner and group only
236        confDirPath = os.path.dirname(self.opt.configDir)
237        try:
238            os.makedirs(confDirPath, mode=0770)
239        except OSError, e:
240            if e.errno != 17:
241                # errno=17 -> file already exists - it's OK if directory is
242                # already present
243                raise SecurityInstallError, \
244                   "Creating configuration directory: %s" % e
245       
246        # Locate conf directory in active egg
247        #
248        # pkg_resources import MUST be go here otherwise in an update to
249        # existing eggs, the latest version will be reported as the one
250        # you're replacing instead of the new one
251        import pkg_resources
252
253        # Get distribution version info
254        serverDistro = pkg_resources.get_distribution('ndg-security-server')
255        eggConfigDir = os.path.join(serverDistro.location, 'ndg', 'security',
256                                    'server', 'conf')
257
258        configDirVers = "%s.%s" % (self.opt.configDir, serverDistro.version)
259        # Copy over conf directory from egg
260        try:
261            shutil.copytree(eggConfigDir, configDirVers)
262        except OSError, e:
263            if e.errno != 17:
264                raise SecurityInstallError, \
265                    "Copying configuration directory: %s" % e
266
267        # Create a symbolic link to the conf.<version> dir - first check the
268        # link doesn't already exist
269        if os.path.islink(self.opt.configDir):
270            os.unlink(self.opt.configDir)
271           
272        try:
273            os.symlink(configDirVers, self.opt.configDir)
274        except OSError, e:
275            raise SecurityInstallError, \
276                "Making a symbolic link %s -> %s: %s" % (self.opt.configDir, 
277                                                         configDirVers, 
278                                                         e)
279if __name__ == "__main__":
280    SecurityInstall()()
281     
Note: See TracBrowser for help on using the repository browser.