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

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

Fix problem with search and replace licence not adding a new line.

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